From 2c173b0ce16613dc1e3b288dcd20e93ca036aa9a Mon Sep 17 00:00:00 2001 From: Thushara-Piyasekara Date: Tue, 9 Apr 2024 17:52:21 +0530 Subject: [PATCH 01/23] Fix immutable BFields not being marked as readonly --- .../io/ballerina/runtime/internal/values/ReadOnlyUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java index 5e527b31679f..0231e94d03c4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ReadOnlyUtils.java @@ -224,8 +224,8 @@ private static BIntersectionType setImmutableIntersectionType(Type type, Set entry : originalFields.entrySet()) { Field originalField = entry.getValue(); fields.put(entry.getKey(), - new BField(getImmutableType(originalField.getFieldType(), unresolvedTypes), - originalField.getFieldName(), originalField.getFlags())); + new BField(getImmutableType(originalField.getFieldType(), unresolvedTypes), + originalField.getFieldName(), originalField.getFlags() | SymbolFlags.READONLY)); } BRecordType immutableRecordType = new BRecordType( From 3e017eccd7048db165a8f5251eb9b3eb9e502eea Mon Sep 17 00:00:00 2001 From: Thushara-Piyasekara Date: Tue, 9 Apr 2024 18:22:58 +0530 Subject: [PATCH 02/23] Update tests with new error message --- .../test/javainterop/basic/StaticMethodTest.java | 5 +++-- .../annotations/annotation_access_negative.bal | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java index 4b56dddbe92e..8151a11969a7 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java @@ -169,9 +169,10 @@ public void testCreateRawDetails() { } @Test(expectedExceptions = BLangTestException.class, - expectedExceptionsMessageRegExp = ".*Invalid update of record field: modification not allowed on readonly " + - "value.*") + expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" + + "\"cannot update 'readonly' field 'name' in record of type 'Details & readonly'\".*") public void testCreateDetails() { + BRunUtil.invoke(result, "testCreateDetails"); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/annotation_access_negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/annotation_access_negative.bal index 462145a9f1c9..c3fa341d4c0b 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/annotation_access_negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/annotation_access_negative.bal @@ -47,8 +47,8 @@ function testRecordTypeAnnotationReadonlyValueEdit() { assertEquality(true, res is error); error resError = res; - assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message()); - assertEquality("Invalid update of record field: modification not allowed on readonly value", + assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message()); + assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'", resError.detail()["message"]); } @@ -73,8 +73,8 @@ function testAnnotationOnObjectTypeReadonlyValueEdit() { assertEquality(true, res is error); error resError = res; - assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message()); - assertEquality("Invalid update of record field: modification not allowed on readonly value", + assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message()); + assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'", resError.detail()["message"]); } @@ -97,8 +97,8 @@ function testAnnotationOnFunctionTypeReadonlyValueEdit() { assertTrue(res is error); error resError = res; - assertEquality("{ballerina/lang.map}InvalidUpdate", resError.message()); - assertEquality("Invalid update of record field: modification not allowed on readonly value", + assertEquality("{ballerina/lang.map}InherentTypeViolation", resError.message()); + assertEquality("cannot update 'readonly' field 'foo' in record of type 'Annot & readonly'", resError.detail()["message"]); } From a4c0d3355c1e4e4f2a9931842e3e338263bb9edd Mon Sep 17 00:00:00 2001 From: Thushara-Piyasekara Date: Wed, 10 Apr 2024 13:19:42 +0530 Subject: [PATCH 03/23] Add tests for InherentTypeViolation consistency --- ...leVsArrayReadonlyErrorConsistencyTest.java | 47 +++++++++++++++++++ ...s_array_readonly_violation_consistency.bal | 21 +++++++++ ...onsistency_without_tuple_Update_method.bal | 13 +++++ 3 files changed, 81 insertions(+) create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java new file mode 100644 index 000000000000..89dce615e08f --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java @@ -0,0 +1,47 @@ +package org.ballerinalang.test.types.readonly; + +import org.ballerinalang.test.BCompileUtil; +import org.ballerinalang.test.BRunUtil; +import org.ballerinalang.test.CompileResult; +import org.ballerinalang.test.exceptions.BLangTestException; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * Tests for the readonly violation error consistency between BTuple type and BRecord type. + * + * @since 2201.9.0 + */ +public class TupleVsArrayReadonlyErrorConsistencyTest { + private CompileResult resultWithTupleUpdateMethod; + private CompileResult resultWithoutTupleUpdateMethod; + + @BeforeClass + public void setup() { + resultWithTupleUpdateMethod = + BCompileUtil.compile("test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal"); + resultWithoutTupleUpdateMethod = BCompileUtil.compile( + "test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal"); + } + + @Test(expectedExceptions = BLangTestException.class, + expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" + + "\"cannot update 'readonly' field 'name' in record of type '\\(Employee & readonly\\)'\".*") + public void testWithTupleUpdateMethod() { + BRunUtil.invoke(resultWithTupleUpdateMethod, "testFrozenAnyArrayElementUpdate"); + } + + @Test(expectedExceptions = BLangTestException.class, + expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" + + "\"cannot update 'readonly' field 'name' in record of type 'Employee & readonly'\".*") + public void testWithoutTupleUpdateMethod() { + BRunUtil.invoke(resultWithoutTupleUpdateMethod, "testFrozenAnyArrayElementUpdate"); + } + + @AfterClass + public void tearDown() { + resultWithTupleUpdateMethod = null; + resultWithoutTupleUpdateMethod = null; + } +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal new file mode 100644 index 000000000000..799a4f457f68 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal @@ -0,0 +1,21 @@ +type Employee record {| + int id; + string name; +|}; + +function testFrozenAnyArrayElementUpdate() returns error? { + Employee e1 = {name: "Em", id: 1000}; + anydata[] i1 = [e1]; + anydata[] i2 = i1.cloneReadOnly(); + Employee e2 = check trap i2[0]; + e2["name"] = "Zee"; + return (); +} + +function testFrozenTupleUpdate() { + Employee e1 = {name: "Em", id: 1000}; + [int, Employee] t1 = [1, e1]; + [int, Employee] t2 = t1.cloneReadOnly(); + Employee e2 = {name: "Zee", id: 1200}; + t2[1] = e2; +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal new file mode 100644 index 000000000000..864ef51ca788 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal @@ -0,0 +1,13 @@ +type Employee record {| + int id; + string name; +|}; + +function testFrozenAnyArrayElementUpdate() returns error? { + Employee e1 = {name: "Em", id: 1000}; + anydata[] i1 = [e1]; + anydata[] i2 = i1.cloneReadOnly(); + Employee e2 = check trap i2[0]; + e2["name"] = "Zee"; + return (); +} From 3ef373ec9a196d972c31f251731504839307e529 Mon Sep 17 00:00:00 2001 From: Thushara-Piyasekara Date: Wed, 10 Apr 2024 15:01:04 +0530 Subject: [PATCH 04/23] Fix CheckStyle violations --- .../readonly/TupleVsArrayReadonlyErrorConsistencyTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java index 89dce615e08f..7c74bc414fbf 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java @@ -21,8 +21,8 @@ public class TupleVsArrayReadonlyErrorConsistencyTest { public void setup() { resultWithTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal"); - resultWithoutTupleUpdateMethod = BCompileUtil.compile( - "test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal"); + resultWithoutTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/" + + "test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal"); } @Test(expectedExceptions = BLangTestException.class, From 6e9b1d9980383e38660e4e1193ee3a3b647a8928 Mon Sep 17 00:00:00 2001 From: Thushara-Piyasekara Date: Thu, 11 Apr 2024 20:58:28 +0530 Subject: [PATCH 05/23] Add license headers --- ...pleVsArrayReadonlyErrorConsistencyTest.java | 18 ++++++++++++++++++ ...vs_array_readonly_violation_consistency.bal | 16 ++++++++++++++++ ...consistency_without_tuple_Update_method.bal | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java index 7c74bc414fbf..6f3a96baf8df 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package org.ballerinalang.test.types.readonly; import org.ballerinalang.test.BCompileUtil; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal index 799a4f457f68..5f5ab46b1259 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal @@ -1,3 +1,19 @@ +// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + type Employee record {| int id; string name; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal index 864ef51ca788..3cceed237e09 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal @@ -1,3 +1,19 @@ +// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). +// +// WSO2 LLC. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + type Employee record {| int id; string name; From 1dbfc97b0b6380de20e2db72032beaf4af057b5e Mon Sep 17 00:00:00 2001 From: Thushara-Piyasekara Date: Mon, 6 May 2024 09:16:54 +0530 Subject: [PATCH 06/23] Update JavaDoc comments for classes --- .../readonly/TupleVsArrayReadonlyErrorConsistencyTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java index 6f3a96baf8df..0dbf845b3687 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java @@ -29,7 +29,7 @@ /** * Tests for the readonly violation error consistency between BTuple type and BRecord type. * - * @since 2201.9.0 + * @since 2201.10.0 */ public class TupleVsArrayReadonlyErrorConsistencyTest { private CompileResult resultWithTupleUpdateMethod; From f460632e8517d472dcf7e62852431bf94e33a245 Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Thu, 15 Aug 2024 10:16:31 +0530 Subject: [PATCH 07/23] Add orderedType check and tests for tuples --- .../ballerina/runtime/api/values/BArray.java | 3 + .../internal/values/TupleValueImpl.java | 34 +- .../src/main/java/module-info.java | 2 +- .../lang.array/src/main/java/module-info.java | 1 + .../org/ballerinalang/langlib/array/Sort.java | 35 +- .../langlib/array/utils/SortUtils.java | 161 +++++++ .../langlib/array/utils/TypePair.java | 47 +++ .../langlib/test/LangLibArrayTest.java | 1 + .../langlib/test/LangLibTupleTest.java | 3 +- .../test/resources/test-src/arraylib_test.bal | 398 ++++++++++++++++++ 10 files changed, 660 insertions(+), 25 deletions(-) create mode 100644 langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java create mode 100644 langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java index efc1e70cb995..5d786140dc9c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java @@ -237,3 +237,6 @@ public interface BArray extends BRefValue, BCollection { long getLength(); } + + + diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index 2bdc52b627bb..f6b4ae374d6c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -23,28 +23,19 @@ import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; -import io.ballerina.runtime.api.values.BArray; -import io.ballerina.runtime.api.values.BIterator; -import io.ballerina.runtime.api.values.BLink; -import io.ballerina.runtime.api.values.BListInitialValueEntry; -import io.ballerina.runtime.api.values.BRefValue; -import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.api.values.BTypedesc; -import io.ballerina.runtime.api.values.BValue; +import io.ballerina.runtime.api.values.*; import io.ballerina.runtime.internal.CycleUtils; import io.ballerina.runtime.internal.TypeChecker; import io.ballerina.runtime.internal.ValueConverter; import io.ballerina.runtime.internal.errors.ErrorCodes; import io.ballerina.runtime.internal.errors.ErrorHelper; import io.ballerina.runtime.internal.errors.ErrorReasons; +import io.ballerina.runtime.internal.types.BType; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.StringJoiner; +import java.util.*; import java.util.stream.IntStream; import static io.ballerina.runtime.api.constants.RuntimeConstants.ARRAY_LANG_LIB; @@ -324,6 +315,25 @@ public void addRefValue(long index, Object value) { refValues[(int) index] = value; } + public boolean checkSortCompatibility(BArray arr, BFunctionPointer function, Set typeList, Integer[] orderedTypeList) { + Type memberType; + for(int i = 0; i < arr.getLength(); i++) { + memberType = TypeUtils.getReferredType(this.tupleType.getTupleTypes().get(i)); + if( memberType != this.tupleType.getTupleTypes().get(0) && function == null) { + return false; + } + typeList.add(memberType); + } + return (Arrays.stream(orderedTypeList).toList().contains(typeList.stream().toList().get(0).getTag()) && + typeList.size() == 1); + } + + public List getElementTypeList() { + List typeList = this.tupleType.getTupleTypes(); + typeList.add(this.tupleType.getRestType()); + return typeList; + } + public void convertStringAndAddRefValue(long index, BString value) { rangeCheck(index, size); int intIndex = (int) index; diff --git a/bvm/ballerina-runtime/src/main/java/module-info.java b/bvm/ballerina-runtime/src/main/java/module-info.java index 385a49becba8..de5947b17a93 100644 --- a/bvm/ballerina-runtime/src/main/java/module-info.java +++ b/bvm/ballerina-runtime/src/main/java/module-info.java @@ -68,7 +68,7 @@ io.ballerina.lang.function, io.ballerina.lang.regexp, io.ballerina.lang.value, io.ballerina.lang.internal; exports io.ballerina.runtime.internal.configurable to io.ballerina.lang.internal; exports io.ballerina.runtime.internal.types to io.ballerina.lang.typedesc, io.ballerina.testerina.runtime, - org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function, io.ballerina.lang.regexp, io.ballerina.testerina.core; + org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function, io.ballerina.lang.regexp, io.ballerina.testerina.core, io.ballerina.lang.array; exports io.ballerina.runtime.observability.metrics.noop; exports io.ballerina.runtime.observability.tracer.noop; exports io.ballerina.runtime.internal.regexp; diff --git a/langlib/lang.array/src/main/java/module-info.java b/langlib/lang.array/src/main/java/module-info.java index 627916960435..25c102fb02d0 100644 --- a/langlib/lang.array/src/main/java/module-info.java +++ b/langlib/lang.array/src/main/java/module-info.java @@ -1,4 +1,5 @@ module io.ballerina.lang.array { requires io.ballerina.runtime; + requires io.ballerina.lang; exports org.ballerinalang.langlib.array; } diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java index 750706c1c0ec..9473bb44b404 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java @@ -18,21 +18,26 @@ package org.ballerinalang.langlib.array; +import io.ballerina.runtime.api.TypeTags; import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; -import io.ballerina.runtime.api.utils.TypeUtils; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BFunctionPointer; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.internal.ValueComparisonUtils; import io.ballerina.runtime.internal.scheduling.Scheduler; +import io.ballerina.runtime.internal.types.*; + +import java.util.*; import static io.ballerina.runtime.api.constants.RuntimeConstants.ARRAY_LANG_LIB; import static io.ballerina.runtime.internal.errors.ErrorReasons.INVALID_TYPE_TO_SORT; import static io.ballerina.runtime.internal.errors.ErrorReasons.getModulePrefixedReason; -import static org.ballerinalang.langlib.array.utils.ArrayUtils.checkIsArrayOnlyOperation; +import static org.ballerinalang.langlib.array.utils.SortUtils.isOrderedType; /** * Native implementation of lang.array:sort((any|error)[], direction, function). @@ -42,12 +47,21 @@ public class Sort { public static BArray sort(BArray arr, Object direction, Object func) { - checkIsArrayOnlyOperation(TypeUtils.getImpliedType(arr.getType()), "sort()"); + BArray sortedArray; BFunctionPointer function = (BFunctionPointer) func; - + Set typeList = new HashSet<>(); + if(arr.getType().getTag() == TypeTags.TUPLE_TAG) { + if(!isOrderedType(arr.getType()) && function == null) { + throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INVALID_TYPE_TO_SORT), + StringUtils.fromString("Valid Key function needed")); + } + typeList = new HashSet<>(((BTupleType)arr.getType()).getTupleTypes()); + if(((BTupleType)arr.getType()).getRestType() != null) { + typeList.add(((BTupleType)arr.getType()).getRestType()); + } + } Object[][] sortArr = new Object[arr.size()][2]; Object[][] sortArrClone = new Object[arr.size()][2]; - if (function != null) { for (int i = 0; i < arr.size(); i++) { sortArr[i][0] = function.call(new Object[]{Scheduler.getStrand(), arr.get(i), true}); @@ -58,15 +72,16 @@ public static BArray sort(BArray arr, Object direction, Object func) { sortArr[i][0] = sortArr[i][1] = arr.get(i); } } - mergesort(sortArr, sortArrClone, 0, sortArr.length - 1, direction.toString()); - - BArray sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType(arr.getElementType())); - + if(arr.getType().getTag() == TypeTags.TUPLE_TAG) { + sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType( + TypeCreator.createUnionType(typeList.stream().toList()))); + } else { + sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType(arr.getElementType())); + } for (int k = 0; k < sortArr.length; k++) { sortedArray.add(k, sortArr[k][1]); } - return sortedArray; } diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java new file mode 100644 index 000000000000..5c707e5f7bca --- /dev/null +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.ballerinalang.langlib.array.utils; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.TypeCreator; +import io.ballerina.runtime.api.types.IntersectionType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.utils.TypeUtils; +import io.ballerina.runtime.internal.TypeChecker; +import io.ballerina.runtime.internal.types.BArrayType; +import io.ballerina.runtime.internal.types.BFiniteType; +import io.ballerina.runtime.internal.types.BTupleType; + +import java.util.*; + +public class SortUtils { + + public static boolean isOrderedType(Type type) { + type = TypeUtils.getImpliedType(type); + switch (type.getTag()) { + case TypeTags.UNION_TAG: + UnionType unionType = (UnionType) type; + if (unionType.isCyclic()) { + return true; + } + Set memberTypes = new HashSet<>(unionType.getMemberTypes()); + Type firstTypeInUnion = getTypeWithEffectiveIntersectionTypes(TypeUtils.getImpliedType( + memberTypes.stream().filter(m -> m.getTag() != TypeTags.NULL_TAG).findFirst(). + orElse(memberTypes.iterator().next()))); + if (firstTypeInUnion.getTag() == TypeTags.NULL_TAG) { + // Union contains only the nil type. + return true; + } + if(!isOrderedType(firstTypeInUnion)) { + return false; + } + for (Type memType : memberTypes) { + memType = TypeUtils.getImpliedType(memType); + if(!isOrderedType(memType) || isDifferentOrderedType(memType, firstTypeInUnion)) { + return false; + } + } + return true; + case TypeTags.ARRAY_TAG: + return isOrderedType(((BArrayType) type).getElementType()); + case TypeTags.TUPLE_TAG: + List tupleTypes = ((BTupleType) type).getTupleTypes(); + if (((BTupleType) type).getRestType() != null) tupleTypes.add(((BTupleType) type).getRestType()); + if(!isOrderedType(tupleTypes.get(0))) { + return false; + } + for (Type memType : tupleTypes) { + if (!isOrderedType(memType) || isDifferentOrderedType(memType, tupleTypes.get(0))) { + return false; + } + } + return true; + case TypeTags.FINITE_TYPE_TAG: + Set valSpace = ((BFiniteType) type).getValueSpace(); + Type baseExprType = TypeUtils.getType(valSpace.iterator().next()); + if (!checkValueSpaceHasSameType((BFiniteType) type, baseExprType)) { + return false; + } + return isOrderedType(baseExprType); + default: + return isSimpleBasicType(type.getTag()); + } + } + + public static Type getTypeWithEffectiveIntersectionTypes(Type bType) { + Type type = TypeUtils.getReferredType(bType); + Type effectiveType = null; + if (type.getTag() == TypeTags.INTERSECTION_TAG) { + effectiveType = ((IntersectionType)type).getEffectiveType(); + type = effectiveType; + } + + if (type.getTag() != TypeTags.UNION_TAG) { + return Objects.requireNonNullElse(effectiveType, bType); + } + + LinkedHashSet members = new LinkedHashSet<>(); + boolean hasDifferentMember = false; + + for (Type memberType : ((UnionType) type).getMemberTypes()) { + effectiveType = getTypeWithEffectiveIntersectionTypes(memberType); + effectiveType = TypeUtils.getImpliedType(effectiveType); + if (effectiveType != memberType) { + hasDifferentMember = true; + } + members.add(effectiveType); + } + + if (hasDifferentMember) { + return TypeCreator.createUnionType(members.stream().toList()); + } + return bType; + } + + public static boolean checkValueSpaceHasSameType(BFiniteType finiteType, Type type) { + Type baseType = TypeUtils.getImpliedType(type); + if (baseType.getTag() == TypeTags.FINITE_TYPE_TAG) { + return checkValueSpaceHasSameType((BFiniteType) baseType, + TypeUtils.getType(finiteType.getValueSpace().iterator().next())); + } + for (Object expr : finiteType.getValueSpace()) { + if(isDifferentOrderedType(TypeUtils.getType(expr), baseType)) { + return false; + } + } + return true; + } + + public static boolean isDifferentOrderedType(Type source, Type target) { + source = TypeUtils.getImpliedType(source); + target = TypeUtils.getImpliedType(target); + if (source.getTag() == TypeTags.NULL_TAG || target.getTag() == TypeTags.NULL_TAG) { + return false; + } + if(checkIfDifferent(source)) { + return true; + } + return !TypeChecker.checkIsType(source, target); + } + + public static boolean isSimpleBasicType(int tag) { + return switch (tag) { + case TypeTags.BYTE_TAG, TypeTags.FLOAT_TAG, TypeTags.DECIMAL_TAG, TypeTags.BOOLEAN_TAG, TypeTags.NULL_TAG -> + true; + default -> tag >= TypeTags.INT_TAG && tag <= TypeTags.CHAR_STRING_TAG; + }; + } + + public static boolean checkIfDifferent(Type s) { + return switch (s.getTag()) { + case TypeTags.TYPE_REFERENCED_TYPE_TAG, TypeTags.ANY_TAG, TypeTags.ANYDATA_TAG, TypeTags.MAP_TAG, + TypeTags.FUTURE_TAG, TypeTags.XML_TAG, TypeTags.JSON_TAG, TypeTags.OBJECT_TYPE_TAG, + TypeTags.RECORD_TYPE_TAG, TypeTags.STREAM_TAG, TypeTags.TABLE_TAG, TypeTags.INVOKABLE_TAG, + TypeTags.ERROR_TAG -> true; + default -> false; + }; + } +} diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java new file mode 100644 index 000000000000..3b0b130c3cba --- /dev/null +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.ballerinalang.langlib.array.utils; + +import io.ballerina.runtime.api.types.Type; + +import java.util.Objects; + +public class TypePair { + Type sourceType; + Type targetType; + + public TypePair(Type sourceType, Type targetType) { + this.sourceType = sourceType; + this.targetType = targetType; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TypePair other)) { + return false; + } + + return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType); + } + + @Override + public int hashCode() { + return Objects.hash(sourceType, targetType); + } +} diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java index f8dc94bbf0e0..925abb141f5e 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java @@ -562,6 +562,7 @@ public Object[] testFunctions() { "testSort8", "testSort9", "testSort10", + "testSortNegative", "testReadOnlyArrayFilter", "testTupleFilter", "testTupleReverse", diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java index 96e425c14df6..0baa6a41c5fa 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java @@ -113,8 +113,7 @@ public void testRemove() { BRunUtil.invoke(compileResult, "testRemove"); } - @Test(expectedExceptions = RuntimeException.class, - expectedExceptionsMessageRegExp = ".*error: \\{ballerina/lang.array\\}OperationNotSupported.*") + @Test public void testSort() { BRunUtil.invoke(compileResult, "testSort"); } diff --git a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal index 3a7ceb07f9a2..5a20a41350d7 100644 --- a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal +++ b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal @@ -906,13 +906,30 @@ function getStudentList() returns Student[] { return studentList; } +function getStudentListForTuples() returns [Student...] { + Student s1 = {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}; + Student s2 = {id: 20, fname: (), fee: 2000.56, impact: 0.45, isUndergrad: false}; + Student s3 = {id: 2, fname: "Dan", fee: (), impact: 0.3, isUndergrad: true}; + Student s4 = {id: 10, fname: "Kate", fee: (0.0 / 0.0), impact: 0.146, isUndergrad: false}; + Student s5 = {id: 3, fname: "Kate", fee: 5000.56, impact: 0.4, isUndergrad: false}; + + [Student...] studentList = [s1, s2, s3, s4, s5]; + + return studentList; +} + function testSort1() { Student[] studentArr = getStudentList(); + [Student...] studentTup = getStudentListForTuples(); Student[] sortedArr = studentArr.sort(array:DESCENDING, isolated function(Student s) returns int { return s.id; }); + Student[] sortedTup = studentTup.sort(array:DESCENDING, isolated function(Student s) returns int { + return s.id; + }); + assertValueEquality(sortedArr[0].toString(), "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); assertValueEquality(sortedArr[1].toString(), @@ -925,10 +942,26 @@ function testSort1() { "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); assertFalse(studentArr == sortedArr); + assertValueEquality(sortedTup[0].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedTup[1].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedTup[2].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedTup[3].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedTup[4].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertFalse(studentArr == sortedTup); + Student[] sortedArr2 = studentArr.sort(array:DESCENDING, isolated function(Student s) returns string? { return s.fname; }); + Student[] sortedTup2 = studentTup.sort(array:DESCENDING, isolated function(Student s) returns string? { + return s.fname; + }); + assertValueEquality(sortedArr2[0].toString(), "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); assertValueEquality(sortedArr2[1].toString(), @@ -941,10 +974,26 @@ function testSort1() { "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); assertFalse(studentArr == sortedArr2); + assertValueEquality(sortedTup2[0].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedTup2[1].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedTup2[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedTup2[3].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedTup2[4].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertFalse(studentArr == sortedArr2); + Student[] sortedArr3 = studentArr.sort(array:ASCENDING, isolated function(Student s) returns float? { return s.fee; }); + Student[] sortedTup3 = studentTup.sort(array:ASCENDING, isolated function(Student s) returns float? { + return s.fee; + }); + assertValueEquality(sortedArr3[0].toString(), "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); assertValueEquality(sortedArr3[1].toString(), @@ -956,10 +1005,25 @@ function testSort1() { assertValueEquality(sortedArr3[4].toString(), "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedTup3[0].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedTup3[1].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedTup3[2].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedTup3[3].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedTup3[4].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + Student[] sortedArr4 = studentArr.sort(array:ASCENDING, isolated function(Student s) returns decimal { return s.impact; }); + Student[] sortedTup4 = studentTup.sort(array:ASCENDING, isolated function(Student s) returns decimal { + return s.impact; + }); + assertValueEquality(sortedArr4[0].toString(), "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); assertValueEquality(sortedArr4[1].toString(), @@ -971,6 +1035,17 @@ function testSort1() { assertValueEquality(sortedArr4[4].toString(), "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedTup4[0].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedTup4[1].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedTup4[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedTup4[3].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedTup4[4].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + Student[] sortedArr5 = sortedArr4.sort(array:ASCENDING, isolated function(Student s) returns boolean { return s.isUndergrad; }); @@ -988,6 +1063,7 @@ function testSort1() { assertFalse(sortedArr4 == sortedArr5); assertValueEquality(getStudentList(), studentArr); // no change to original array + assertValueEquality(getStudentListForTuples(), studentTup); } function testSort2() { @@ -1118,6 +1194,7 @@ function testSort3() returns int[] { function testSort4() { [Grade, int][] grades = [["A+", 2], ["A-", 3], ["B", 3], ["C", 2]]; + [[Grade, int]...] gradesTup = [["A+", 2], ["A-", 3], ["B", 3], ["C", 2]]; [Grade, int][] sortedArr = grades.sort(array:ASCENDING, isolated function([Grade, int] val) returns float[] { if (val[0] == "A+") { @@ -1126,20 +1203,38 @@ function testSort4() { return [val[1], 5.2]; }); + [Grade, int][] sortedTup = gradesTup.sort(array:ASCENDING, isolated function([Grade, int] val) returns float[] { + if (val[0] == "A+") { + return [val[1], 6.5]; + } + return [val[1], 5.2]; + }); + assertValueEquality(sortedArr[0].toString(), "[\"C\",2]"); assertValueEquality(sortedArr[1].toString(), "[\"A+\",2]"); assertValueEquality(sortedArr[2].toString(), "[\"A-\",3]"); assertValueEquality(sortedArr[3].toString(), "[\"B\",3]"); assertValueEquality([["A+", 2], ["A-", 3], ["B", 3], ["C", 2]], grades); // no change to original array + + assertValueEquality(sortedTup[0].toString(), "[\"C\",2]"); + assertValueEquality(sortedTup[1].toString(), "[\"A+\",2]"); + assertValueEquality(sortedTup[2].toString(), "[\"A-\",3]"); + assertValueEquality(sortedTup[3].toString(), "[\"B\",3]"); + assertValueEquality([["A+", 2], ["A-", 3], ["B", 3], ["C", 2]], gradesTup); // no change to original array } function testSort5() { Student[] studentArr = getStudentList(); + [Student...] studentTup = getStudentListForTuples(); Student[] sortedArr = studentArr.sort(array:DESCENDING, isolated function(Student s) returns string? { return getFullName(s.id, s.fname); }); + Student[] sortedTup = studentTup.sort(array:DESCENDING, isolated function(Student s) returns string? { + return getFullName(s.id, s.fname); + }); + assertValueEquality(sortedArr[0].toString(), "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); assertValueEquality(sortedArr[1].toString(), @@ -1151,6 +1246,18 @@ function testSort5() { assertValueEquality(sortedArr[4].toString(), "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); assertValueEquality(getStudentList(), studentArr); // no change to original array + + assertValueEquality(sortedTup[0].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedTup[1].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedTup[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedTup[3].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedTup[4].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(getStudentListForTuples(), studentTup); // no change to original array } isolated function getFullName(int id, string? name) returns string? { @@ -1167,6 +1274,7 @@ type StringOrStudent string|Student; function testSort6() { anydata[] arr = [90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]]; + [anydata...] tup = [90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]]; anydata[] sortedArr = arr.sort(array:ASCENDING, isolated function(anydata a) returns int? { if (a is int) { @@ -1181,40 +1289,79 @@ function testSort6() { return (); }); + anydata[] sortedTup = tup.sort(array:ASCENDING, isolated function(anydata a) returns int? { + if (a is int) { + return a; + } else if (a is float) { + return a; + } else if (a is boolean) { + return 0; + } else if (a is map) { + return -1; + } + return (); + }); + assertValueEquality(sortedArr.toString(), "[{\"k\":\"Bar\"},true,1,2.0,3,12.09,32,90,100,\"AA\",[\"BB\",true]]"); assertValueEquality([90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]], arr); + assertValueEquality(sortedTup.toString(), + "[{\"k\":\"Bar\"},true,1,2.0,3,12.09,32,90,100,\"AA\",[\"BB\",true]]"); + assertValueEquality([90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]], tup); + string?[] arr2 = ["Hello", "World!", (), "from", "Ballerina"]; + [(string?)...] tup2 = ["Hello", "World!", (), "from", "Ballerina"]; string?[] sortedArr2 = arr2.sort(); assertValueEquality(sortedArr2.toString(), "[\"Ballerina\",\"Hello\",\"World!\",\"from\",null]"); + string?[] sortedTup2 = tup2.sort(); + assertValueEquality(sortedTup2.toString(), "[\"Ballerina\",\"Hello\",\"World!\",\"from\",null]"); + Obj obj1 = new Obj(1, 1); Obj obj2 = new Obj(1, 2); Obj obj3 = new Obj(1, 10); Obj[] arr3 = [obj1, obj2, obj3]; + [Obj...] tup3 = [obj1, obj2, obj3]; Obj[] sortedArr3 = arr3.sort(array:DESCENDING, isolated function(Obj obj) returns int { return obj.j; }); + Obj[] sortedTup3 = tup3.sort(array:DESCENDING, isolated function(Obj obj) returns int { + return obj.j; + }); + assertValueEquality(sortedArr3[0].j, 10); assertValueEquality(sortedArr3[1].j, 2); assertValueEquality(sortedArr3[2].j, 1); + assertValueEquality(sortedTup3[0].j, 10); + assertValueEquality(sortedTup3[1].j, 2); + assertValueEquality(sortedTup3[2].j, 1); + int[2]|int[] arr4 = [1, 9, 3, 21, 0, 7]; + [int, int]|[int...] tup4 = [1, 9, 3, 21, 0, 7]; int[2]|int[] sortedArr4 = arr4.sort(array:ASCENDING, isolated function(int i) returns int { return i; }); + int[2]|int[] sortedTup4 = tup4.sort(array:ASCENDING, isolated function(int i) returns int { + return i; + }); + assertValueEquality(sortedArr4.toString(), "[0,1,3,7,9,21]"); + assertValueEquality(sortedTup4.toString(), "[0,1,3,7,9,21]"); int[] arr5 = [2, 0, 12, 1, 23, 3, 100, 55]; + [int...] tup5 = [2, 0, 12, 1, 23, 3, 100, 55]; int[] sortedArr5 = arr5.sort(array:DESCENDING); + int[] sortedTup5 = tup5.sort(array:DESCENDING); assertValueEquality(sortedArr5.toString(), "[100,55,23,12,3,2,1,0]"); + assertValueEquality(sortedTup5.toString(), "[100,55,23,12,3,2,1,0]"); string?[] sortedArr6 = arr2.sort(array:DESCENDING, isolated function(string? s) returns string?[]? { if (s is string) { @@ -1223,7 +1370,15 @@ function testSort6() { return (); }); + string?[] sortedTup6 = tup2.sort(array:DESCENDING, isolated function(string? s) returns string?[]? { + if (s is string) { + return [s, "A"]; + } + return (); + }); + assertValueEquality(sortedArr6.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); + assertValueEquality(sortedTup6.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); string?[] sortedArr7 = arr2.sort(array:ASCENDING, isolated function(string? s) returns string?[] { if (s is string) { @@ -1232,25 +1387,43 @@ function testSort6() { return ["W", "A"]; }); + string?[] sortedTup7 = tup2.sort(array:ASCENDING, isolated function(string? s) returns string?[] { + if (s is string) { + return [s, "A"]; + } + return ["W", "A"]; + }); + assertValueEquality(sortedArr7.toString(), "[\"Ballerina\",\"Hello\",null,\"World!\",\"from\"]"); + assertValueEquality(sortedTup7.toString(), "[\"Ballerina\",\"Hello\",null,\"World!\",\"from\"]"); int[] sortedArr8 = arr5.sort(array:ASCENDING, ()); + int[] sortedTup8 = tup5.sort(array:ASCENDING, ()); assertValueEquality(sortedArr8.toString(), "[0,1,2,3,12,23,55,100]"); + assertValueEquality(sortedTup8.toString(), "[0,1,2,3,12,23,55,100]"); Grade[] arr6 = ["A+", "B+", "C", "F", "A-", "C", "A+", "B"]; + [Grade...] tup6 = ["A+", "B+", "C", "F", "A-", "C", "A+", "B"]; Grade[] sortedArr9 = arr6.sort(array:DESCENDING, isolated function(Grade grade) returns string { return grade; }); + Grade[] sortedTup9 = arr6.sort(array:DESCENDING, isolated function(Grade grade) returns string { + return grade; + }); + assertValueEquality(sortedArr9.toString(), "[\"F\",\"C\",\"C\",\"B+\",\"B\",\"A-\",\"A+\",\"A+\"]"); assertValueEquality(["A+", "B+", "C", "F", "A-", "C", "A+", "B"], arr6); // no change to arr6 + assertValueEquality(sortedTup9.toString(), "[\"F\",\"C\",\"C\",\"B+\",\"B\",\"A-\",\"A+\",\"A+\"]"); + assertValueEquality(["A+", "B+", "C", "F", "A-", "C", "A+", "B"], arr6); // no change to tup6 Student s1 = {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}; Student s2 = {id: 2, fname: "Dan", fee: (), impact: 0.3, isUndergrad: true}; Student s3 = {id: 10, fname: "Kate", fee: (0.0 / 0.0), impact: 0.146, isUndergrad: false}; StringOrStudent[] arr7 = ["Anne", s3, s1, "James", "Frank", s2]; + [StringOrStudent...] tup7 = ["Anne", s3, s1, "James", "Frank", s2]; StringOrStudent[] sortedArr10 = arr7.sort(array:ASCENDING, isolated function(StringOrStudent sp) returns string? { if (sp is Student) { @@ -1260,6 +1433,14 @@ function testSort6() { } }); + StringOrStudent[] sortedTup10 = tup7.sort(array:ASCENDING, isolated function(StringOrStudent sp) returns string? { + if (sp is Student) { + return sp.fname; + } else { + return sp; + } + }); + assertValueEquality(sortedArr10[0].toString(), "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); assertValueEquality(sortedArr10[1].toString(), "Anne"); @@ -1271,20 +1452,45 @@ function testSort6() { "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); assertValueEquality(["Anne", s3, s1, "James", "Frank", s2], arr7); // no change to arr7 + assertValueEquality(sortedTup10[0].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedTup10[1].toString(), "Anne"); + assertValueEquality(sortedTup10[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedTup10[3].toString(), "Frank"); + assertValueEquality(sortedTup10[4].toString(), "James"); + assertValueEquality(sortedTup10[5].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(["Anne", s3, s1, "James", "Frank", s2], tup7); // no change to tup7 + int[] sortedArr11 = array:sort(arr5); + [int...] sortedTup11 = array:sort(tup5); assertValueEquality(sortedArr11.toString(), "[0,1,2,3,12,23,55,100]"); assertValueEquality([2, 0, 12, 1, 23, 3, 100, 55], arr5); // no change to arr5 assertValueEquality([0, 1, 2, 3, 12, 23, 55, 100], sortedArr8); // no change to sortedArr8 + assertValueEquality(sortedTup11.toString(), "[0,1,2,3,12,23,55,100]"); + assertValueEquality([2, 0, 12, 1, 23, 3, 100, 55], tup5); // no change to tup5 + assertValueEquality([0, 1, 2, 3, 12, 23, 55, 100], sortedTup8); // no change to sortedTup8 + int[2]|int[] sortedArr12 = array:sort(arr4, array:DESCENDING, isolated function(int i) returns int { return i; }); + int[2]|int[] sortedTup12 = array:sort(tup4, array:DESCENDING, isolated function(int i) returns int { + return i; + }); + assertValueEquality(sortedArr12.toString(), "[21,9,7,3,1,0]"); assertValueEquality([1, 9, 3, 21, 0, 7], arr4); // no change to arr4 + assertValueEquality(sortedTup12.toString(), "[21,9,7,3,1,0]"); + assertValueEquality([1, 9, 3, 21, 0, 7], tup4); // no change to tup4 + string?[] sortedArr13 = array:sort(arr2, array:DESCENDING); + string?[] sortedTup13 = array:sort(tup2, array:DESCENDING); assertValueEquality(sortedArr13.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); + assertValueEquality(sortedTup13.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); } function testSort7() { @@ -1309,7 +1515,29 @@ function testSort7() { [1.8, (0.0 / 0.0)] ]; + [(float?[])...] tup = [ + [1.8, 2.89, 5, 70, 90], + [(), 4], + [1.8, 2.89, 5, 70], + [(0.0 / 0.0), 9, 8, 10], + [ + 1.8, + 2.89, + 5, + 70, + () + ], + [1.8, 2.89, 5], + [1.8, 2.89, 4], + [1.8, 2.89], + [2.8, 2.89, 5, 70, 90], + [3], + [1.8, 2.89, 5, 70, (0.0 / 0.0)], + [1.8, (0.0 / 0.0)] + ]; + float?[][] sortedArr = arr.sort(array:DESCENDING); + float?[][] sortedTup = tup.sort(array:DESCENDING); assertValueEquality(sortedArr[0], [3.0]); assertValueEquality(sortedArr[1], [2.8, 2.89, 5.0, 70.0, 90.0]); @@ -1324,10 +1552,27 @@ function testSort7() { assertValueEquality(sortedArr[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); assertValueEquality(sortedArr[11], [(), 4.0]); + assertValueEquality(sortedTup[0], [3.0]); + assertValueEquality(sortedTup[1], [2.8, 2.89, 5.0, 70.0, 90.0]); + assertValueEquality(sortedTup[2], [1.8, 2.89, 5.0, 70.0, 90.0]); + assertValueEquality(sortedTup[3], [1.8, 2.89, 5.0, 70.0, (0.0 / 0.0)]); + assertValueEquality(sortedTup[4], [1.8, 2.89, 5.0, 70.0, ()]); + assertValueEquality(sortedTup[5], [1.8, 2.89, 5.0, 70.0]); + assertValueEquality(sortedTup[6], [1.8, 2.89, 5.0]); + assertValueEquality(sortedTup[7], [1.8, 2.89, 4.0]); + assertValueEquality(sortedTup[8], [1.8, 2.89]); + assertValueEquality(sortedTup[9], [1.8, (0.0 / 0.0)]); + assertValueEquality(sortedTup[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); + assertValueEquality(sortedTup[11], [(), 4.0]); + float?[][] sortedArr2 = arr.sort(array:ASCENDING, isolated function(float?[] x) returns float?[] { return x; }); + float?[][] sortedTup2 = tup.sort(array:ASCENDING, isolated function(float?[] x) returns float?[] { + return x; + }); + assertValueEquality(sortedArr2[0], [1.8, 2.89]); assertValueEquality(sortedArr2[1], [1.8, 2.89, 4.0]); assertValueEquality(sortedArr2[2], [1.8, 2.89, 5.0]); @@ -1341,24 +1586,50 @@ function testSort7() { assertValueEquality(sortedArr2[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); assertValueEquality(sortedArr2[11], [(), 4.0]); + assertValueEquality(sortedTup2[0], [1.8, 2.89]); + assertValueEquality(sortedTup2[1], [1.8, 2.89, 4.0]); + assertValueEquality(sortedTup2[2], [1.8, 2.89, 5.0]); + assertValueEquality(sortedTup2[3], [1.8, 2.89, 5.0, 70.0]); + assertValueEquality(sortedTup2[4], [1.8, 2.89, 5.0, 70.0, 90.0]); + assertValueEquality(sortedTup2[5], [1.8, 2.89, 5.0, 70.0, (0.0 / 0.0)]); + assertValueEquality(sortedTup2[6], [1.8, 2.89, 5.0, 70.0, ()]); + assertValueEquality(sortedTup2[7], [1.8, (0.0 / 0.0)]); + assertValueEquality(sortedTup2[8], [2.8, 2.89, 5.0, 70.0, 90.0]); + assertValueEquality(sortedTup2[9], [3.0]); + assertValueEquality(sortedTup2[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); + assertValueEquality(sortedTup2[11], [(), 4.0]); + int[][] arr2 = [[1, 9, 2], [0, 9, 1], [1, 7, 5], [9, 8, 2], [9, 8, 1]]; + [(int[])...] tup2 = [[1, 9, 2], [0, 9, 1], [1, 7, 5], [9, 8, 2], [9, 8, 1]]; int[][] sortedArr3 = arr2.sort(); + int[][] sortedTup3 = tup2.sort(); assertValueEquality(sortedArr3[0], [0, 9, 1]); assertValueEquality(sortedArr3[1], [1, 7, 5]); assertValueEquality(sortedArr3[2], [1, 9, 2]); assertValueEquality(sortedArr3[3], [9, 8, 1]); assertValueEquality(sortedArr3[4], [9, 8, 2]); + + assertValueEquality(sortedTup3[0], [0, 9, 1]); + assertValueEquality(sortedTup3[1], [1, 7, 5]); + assertValueEquality(sortedTup3[2], [1, 9, 2]); + assertValueEquality(sortedTup3[3], [9, 8, 1]); + assertValueEquality(sortedTup3[4], [9, 8, 2]); } function testSort8() { [int...][] arr = [[10, 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0]]; + [([int...])...] tup = [[10, 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0]]; [int...][] sortedArr = arr.sort(array:ASCENDING, isolated function([int...] x) returns int[] { return x; }); + [int...][] sortedTup = tup.sort(array:ASCENDING, isolated function([int...] x) returns int[] { + return x; + }); + assertValueEquality(sortedArr[0], [0, 9, 5]); assertValueEquality(sortedArr[1], [1, 1, 0]); assertValueEquality(sortedArr[2], [1, 2, 0]); @@ -1366,12 +1637,24 @@ function testSort8() { assertValueEquality(sortedArr[4], [1, 2, 5]); assertValueEquality(sortedArr[5], [10, 2, 0]); + assertValueEquality(sortedTup[0], [0, 9, 5]); + assertValueEquality(sortedTup[1], [1, 1, 0]); + assertValueEquality(sortedTup[2], [1, 2, 0]); + assertValueEquality(sortedTup[3], [1, 2, 0, 7]); + assertValueEquality(sortedTup[4], [1, 2, 5]); + assertValueEquality(sortedTup[5], [10, 2, 0]); + [int?...][] arr2 = [[(), 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0], [0, (), 9]]; + [([int?...])...] tup2 = [[(), 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0], [0, (), 9]]; [int?...][] sortedArr2 = arr2.sort(array:DESCENDING, isolated function(int?[] x) returns int?[] { return x; }); + [int?...][] sortedTup2 = tup2.sort(array:DESCENDING, isolated function(int?[] x) returns int?[] { + return x; + }); + assertValueEquality(sortedArr2[0], [1, 2, 5]); assertValueEquality(sortedArr2[1], [1, 2, 0, 7]); assertValueEquality(sortedArr2[2], [1, 2, 0]); @@ -1380,32 +1663,58 @@ function testSort8() { assertValueEquality(sortedArr2[5], [0, (), 9]); assertValueEquality(sortedArr2[6], [(), 2, 0]); + assertValueEquality(sortedTup2[0], [1, 2, 5]); + assertValueEquality(sortedTup2[1], [1, 2, 0, 7]); + assertValueEquality(sortedTup2[2], [1, 2, 0]); + assertValueEquality(sortedTup2[3], [1, 1, 0]); + assertValueEquality(sortedTup2[4], [0, 9, 5]); + assertValueEquality(sortedTup2[5], [0, (), 9]); + assertValueEquality(sortedTup2[6], [(), 2, 0]); + [int, boolean...][] arr3 = [[3, true, true, true], [5, true, false, true], [1, false, false]]; + [([int, boolean...])...] tup3 = [[3, true, true, true], [5, true, false, true], [1, false, false]]; [int, boolean...][] sortedArr3 = arr3.sort(array:ASCENDING, isolated function([int, boolean...] x) returns boolean[] { return [x[1], x[2]]; }); + [int, boolean...][] sortedTup3 = tup3.sort(array:ASCENDING, isolated function([int, boolean...] x) returns boolean[] { + return [x[1], x[2]]; + }); + assertValueEquality(sortedArr3[0], [1, false, false]); assertValueEquality(sortedArr3[1], [5, true, false, true]); assertValueEquality(sortedArr3[2], [3, true, true, true]); + + assertValueEquality(sortedTup3[0], [1, false, false]); + assertValueEquality(sortedTup3[1], [5, true, false, true]); + assertValueEquality(sortedTup3[2], [3, true, true, true]); } function testSort9() { strings:Char[] arr = ["s", "a", "b", "M", "Z"]; + [strings:Char...] tup = ["s", "a", "b", "M", "Z"]; strings:Char[] sortedArr = arr.sort(array:DESCENDING); + strings:Char[] sortedTup = tup.sort(array:DESCENDING); assertValueEquality(sortedArr.toString(), "[\"s\",\"b\",\"a\",\"Z\",\"M\"]"); + assertValueEquality(sortedTup.toString(), "[\"s\",\"b\",\"a\",\"Z\",\"M\"]"); int[] arr2 = [4294967295, 4194967295, 4294967290, 4284967295, 3294967295, 1294967295]; + [int...] tup2 = [4294967295, 4194967295, 4294967290, 4284967295, 3294967295, 1294967295]; int[] sortedArr2 = arr2.sort(); + int[] sortedTup2 = tup2.sort(); assertValueEquality(sortedArr2.toString(), "[1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]"); + assertValueEquality(sortedTup2.toString(), + "[1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]"); ints:Signed32[] arr3 = [2147483647, -2147483648, 2147483637, -1147483648, -2137483648, 1147483647]; + [ints:Signed32...] tup3 = [2147483647, -2147483648, 2147483637, -1147483648, -2137483648, 1147483647]; ints:Signed32[] sortedArr3 = arr3.sort(); + ints:Signed32[] sortedTup3 = tup3.sort(); assertValueEquality(sortedArr3[0], -2147483648); assertValueEquality(sortedArr3[1], -2137483648); @@ -1414,9 +1723,18 @@ function testSort9() { assertValueEquality(sortedArr3[4], 2147483637); assertValueEquality(sortedArr3[5], 2147483647); + assertValueEquality(sortedTup3[0], -2147483648); + assertValueEquality(sortedTup3[1], -2137483648); + assertValueEquality(sortedTup3[2], -1147483648); + assertValueEquality(sortedTup3[3], 1147483647); + assertValueEquality(sortedTup3[4], 2147483637); + assertValueEquality(sortedTup3[5], 2147483647); + ints:Signed16[] arr4 = [32765, -32768, 32767, -32668, -30768, 32567]; + [ints:Signed16...] tup4 = [32765, -32768, 32767, -32668, -30768, 32567]; ints:Signed16[] sortedArr4 = arr4.sort(array:DESCENDING); + ints:Signed16[] sortedTup4 = tup4.sort(array:DESCENDING); assertValueEquality(sortedArr4[0], 32767); assertValueEquality(sortedArr4[1], 32765); @@ -1425,9 +1743,18 @@ function testSort9() { assertValueEquality(sortedArr4[4], -32668); assertValueEquality(sortedArr4[5], -32768); + assertValueEquality(sortedTup4[0], 32767); + assertValueEquality(sortedTup4[1], 32765); + assertValueEquality(sortedTup4[2], 32567); + assertValueEquality(sortedTup4[3], -30768); + assertValueEquality(sortedTup4[4], -32668); + assertValueEquality(sortedTup4[5], -32768); + ints:Signed8[] arr5 = [-100, -123, 100, 67, -34, 52]; + [ints:Signed8...] tup5 = [-100, -123, 100, 67, -34, 52]; ints:Signed8[] sortedArr5 = arr5.sort(); + ints:Signed8[] sortedTup5 = tup5.sort(); assertValueEquality(sortedArr5[0], -123); assertValueEquality(sortedArr5[1], -100); @@ -1436,12 +1763,24 @@ function testSort9() { assertValueEquality(sortedArr5[4], 67); assertValueEquality(sortedArr5[5], 100); + assertValueEquality(sortedTup5[0], -123); + assertValueEquality(sortedTup5[1], -100); + assertValueEquality(sortedTup5[2], -34); + assertValueEquality(sortedTup5[3], 52); + assertValueEquality(sortedTup5[4], 67); + assertValueEquality(sortedTup5[5], 100); + ints:Unsigned32[] arr6 = [50, 4294967295, 0, 4294957295, 4294967294, 123, 214967295]; + [ints:Unsigned32...] tup6 = [50, 4294967295, 0, 4294957295, 4294967294, 123, 214967295]; ints:Unsigned32[] sortedArr6 = arr6.sort(array:ASCENDING, isolated function(ints:Unsigned32 x) returns ints:Unsigned32 { return x; }); + ints:Unsigned32[] sortedTup6 = tup6.sort(array:ASCENDING, isolated function(ints:Unsigned32 x) returns ints:Unsigned32 { + return x; + }); + assertValueEquality(sortedArr6[0], 0); assertValueEquality(sortedArr6[1], 50); assertValueEquality(sortedArr6[2], 123); @@ -1450,9 +1789,19 @@ function testSort9() { assertValueEquality(sortedArr6[5], 4294967294); assertValueEquality(sortedArr6[6], 4294967295); + assertValueEquality(sortedTup6[0], 0); + assertValueEquality(sortedTup6[1], 50); + assertValueEquality(sortedTup6[2], 123); + assertValueEquality(sortedTup6[3], 214967295); + assertValueEquality(sortedTup6[4], 4294957295); + assertValueEquality(sortedTup6[5], 4294967294); + assertValueEquality(sortedTup6[6], 4294967295); + ints:Unsigned16[] arr7 = [450, 65335, 0, 12, 65535, 12500, 4]; + [ints:Unsigned16...] tup7 = [450, 65335, 0, 12, 65535, 12500, 4]; ints:Unsigned16[] sortedArr7 = arr7.sort(array:DESCENDING); + ints:Unsigned16[] sortedTup7 = arr7.sort(array:DESCENDING); assertValueEquality(sortedArr7[0], 65535); assertValueEquality(sortedArr7[1], 65335); @@ -1462,9 +1811,19 @@ function testSort9() { assertValueEquality(sortedArr7[5], 4); assertValueEquality(sortedArr7[6], 0); + assertValueEquality(sortedTup7[0], 65535); + assertValueEquality(sortedTup7[1], 65335); + assertValueEquality(sortedTup7[2], 12500); + assertValueEquality(sortedTup7[3], 450); + assertValueEquality(sortedTup7[4], 12); + assertValueEquality(sortedTup7[5], 4); + assertValueEquality(sortedTup7[6], 0); + ints:Unsigned8[] arr8 = [221, 100, 0, 255, 24, 9, 2]; + [ints:Unsigned8...] tup8 = [221, 100, 0, 255, 24, 9, 2]; ints:Unsigned8[] sortedArr8 = arr8.sort(); + ints:Unsigned8[] sortedTup8 = tup8.sort(); assertValueEquality(sortedArr8[0], 0); assertValueEquality(sortedArr8[1], 2); @@ -1473,14 +1832,25 @@ function testSort9() { assertValueEquality(sortedArr8[4], 100); assertValueEquality(sortedArr8[5], 221); assertValueEquality(sortedArr8[6], 255); + + assertValueEquality(sortedTup8[0], 0); + assertValueEquality(sortedTup8[1], 2); + assertValueEquality(sortedTup8[2], 9); + assertValueEquality(sortedTup8[3], 24); + assertValueEquality(sortedTup8[4], 100); + assertValueEquality(sortedTup8[5], 221); + assertValueEquality(sortedTup8[6], 255); } function testSort10() { int[] arr = [10, 1, 3, 2, 0, 6]; + [int...] tup = [10, 1, 3, 2, 0, 6]; int[] sortedArr = arr.sort(array:ASCENDING, (i) => i); + int[] sortedTup = tup.sort(array:ASCENDING, (i) => i); assertValueEquality(sortedArr.toString(), "[0,1,2,3,6,10]"); + assertValueEquality(sortedTup.toString(), "[0,1,2,3,6,10]"); final int methodInt1 = 2; var addFunc1 = isolated function(int funcInt1) returns (int) { @@ -1494,27 +1864,55 @@ function testSort10() { }; int[] sortedArr2 = arr.sort(array:DESCENDING, addFunc1); + int[] sortedTup2 = tup.sort(array:DESCENDING, addFunc1); assertValueEquality(sortedArr2.toString(), "[10,6,3,2,1,0]"); + assertValueEquality(sortedTup2.toString(), "[10,6,3,2,1,0]"); int[] sortedArr3 = array:sort(arr, array:ASCENDING, isolated function(int x) returns string[] => [x.toString(), "World"]); + int[] sortedTup3 = array:sort(tup, array:ASCENDING, isolated function(int x) returns string[] => [x.toString(), "World"]); assertValueEquality(sortedArr3.toString(), "[0,1,10,2,3,6]"); + assertValueEquality(sortedTup3.toString(), "[0,1,10,2,3,6]"); int[] sortedArr4 = arr.sort(array:DESCENDING, (i) => i.toString()); + int[] sortedTup4 = tup.sort(array:DESCENDING, (i) => i.toString()); assertValueEquality(sortedArr4, [6, 3, 2, 10, 1, 0]); + assertValueEquality(sortedTup4, [6, 3, 2, 10, 1, 0]); int?[] arr2 = [(), 1, 3, 10, 0, 6]; + [int?...] tup2 = [(), 1, 3, 10, 0, 6]; int?[] sortedArr5 = arr2.sort(array:DESCENDING, (i) => i); + int?[] sortedTup5 = tup2.sort(array:DESCENDING, (i) => i); assertValueEquality(sortedArr5, [10, 6, 3, 1, 0, ()]); + assertValueEquality(sortedTup5, [10, 6, 3, 1, 0, ()]); int[] arr3 = []; + [int...] tup3 = []; int[] sortedArr6 = arr3.sort(array:DESCENDING, (i) => i); + int[] sortedTup6 = tup3.sort(array:DESCENDING, (i) => i); assertValueEquality(sortedArr6, []); + assertValueEquality(sortedTup6, []); +} + +function testSortNegative() { + [int, float] tup1 = [5, 7.3]; + [int|float, float] tup2 = [5, 7.3]; + [Grade, Student] tup3 = ["A", {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}]; + [15|17, 15|17|21, 15|17|"hello"] tup4 = [15, 21, 17]; + anydata[][] items = [tup1, tup2, tup3, tup4]; + foreach anydata[] item in items { + any|error res = trap function:call(array:sort, item); + assertTrue(res is error); + if(res is error) { + assertValueEquality("{ballerina/lang.array}SortOperationError", res.message()); + assertValueEquality("Valid Key function needed", checkpanic res.detail()["message"]); + } + } } function testTupleReverse() { From 3921949e228014e180ff786f0abf5a218026d7c9 Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Thu, 15 Aug 2024 11:28:47 +0530 Subject: [PATCH 08/23] Remove unused methods --- .../ballerina/runtime/api/values/BArray.java | 5 +---- .../internal/values/TupleValueImpl.java | 19 ------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java index 5d786140dc9c..02d729122639 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java @@ -236,7 +236,4 @@ public interface BArray extends BRefValue, BCollection { void setLength(long i); long getLength(); -} - - - +} \ No newline at end of file diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index c1b7e3cfad45..b5fc11d92692 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -315,25 +315,6 @@ public void addRefValue(long index, Object value) { refValues[(int) index] = value; } - public boolean checkSortCompatibility(BArray arr, BFunctionPointer function, Set typeList, Integer[] orderedTypeList) { - Type memberType; - for(int i = 0; i < arr.getLength(); i++) { - memberType = TypeUtils.getReferredType(this.tupleType.getTupleTypes().get(i)); - if( memberType != this.tupleType.getTupleTypes().get(0) && function == null) { - return false; - } - typeList.add(memberType); - } - return (Arrays.stream(orderedTypeList).toList().contains(typeList.stream().toList().get(0).getTag()) && - typeList.size() == 1); - } - - public List getElementTypeList() { - List typeList = this.tupleType.getTupleTypes(); - typeList.add(this.tupleType.getRestType()); - return typeList; - } - public void convertStringAndAddRefValue(long index, BString value) { rangeCheck(index, size); int intIndex = (int) index; From 4a55addb5272da9dccbeefd2cbb0be654e20464c Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Thu, 15 Aug 2024 11:31:12 +0530 Subject: [PATCH 09/23] Add newline to EOF --- .../src/main/java/io/ballerina/runtime/api/values/BArray.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java index 02d729122639..efc1e70cb995 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BArray.java @@ -236,4 +236,4 @@ public interface BArray extends BRefValue, BCollection { void setLength(long i); long getLength(); -} \ No newline at end of file +} From f0a1e779b2a86bc778bec884c7906bcec6582596 Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Thu, 15 Aug 2024 11:43:33 +0530 Subject: [PATCH 10/23] Refactor code --- .../runtime/internal/values/TupleValueImpl.java | 15 ++++++++++++--- langlib/lang.array/src/main/java/module-info.java | 1 - 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index b5fc11d92692..baf8b1029ff4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -23,19 +23,28 @@ import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; -import io.ballerina.runtime.api.values.*; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BIterator; +import io.ballerina.runtime.api.values.BLink; +import io.ballerina.runtime.api.values.BListInitialValueEntry; +import io.ballerina.runtime.api.values.BRefValue; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BTypedesc; +import io.ballerina.runtime.api.values.BValue; import io.ballerina.runtime.internal.CycleUtils; import io.ballerina.runtime.internal.TypeChecker; import io.ballerina.runtime.internal.ValueConverter; import io.ballerina.runtime.internal.errors.ErrorCodes; import io.ballerina.runtime.internal.errors.ErrorHelper; import io.ballerina.runtime.internal.errors.ErrorReasons; -import io.ballerina.runtime.internal.types.BType; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; import java.util.stream.IntStream; import static io.ballerina.runtime.api.constants.RuntimeConstants.ARRAY_LANG_LIB; diff --git a/langlib/lang.array/src/main/java/module-info.java b/langlib/lang.array/src/main/java/module-info.java index 25c102fb02d0..627916960435 100644 --- a/langlib/lang.array/src/main/java/module-info.java +++ b/langlib/lang.array/src/main/java/module-info.java @@ -1,5 +1,4 @@ module io.ballerina.lang.array { requires io.ballerina.runtime; - requires io.ballerina.lang; exports org.ballerinalang.langlib.array; } From e0837715fa7ace3a67e0fa0e29cc6ae6a478f82f Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Thu, 15 Aug 2024 13:54:03 +0530 Subject: [PATCH 11/23] Fix checkstyle issue --- .../org/ballerinalang/langlib/array/Sort.java | 17 +++++++------- .../langlib/array/utils/SortUtils.java | 22 ++++++++++++------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java index 9473bb44b404..fe0f4feb327c 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java @@ -30,9 +30,10 @@ import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.internal.ValueComparisonUtils; import io.ballerina.runtime.internal.scheduling.Scheduler; -import io.ballerina.runtime.internal.types.*; +import io.ballerina.runtime.internal.types.BTupleType; -import java.util.*; +import java.util.HashSet; +import java.util.Set; import static io.ballerina.runtime.api.constants.RuntimeConstants.ARRAY_LANG_LIB; import static io.ballerina.runtime.internal.errors.ErrorReasons.INVALID_TYPE_TO_SORT; @@ -50,14 +51,14 @@ public static BArray sort(BArray arr, Object direction, Object func) { BArray sortedArray; BFunctionPointer function = (BFunctionPointer) func; Set typeList = new HashSet<>(); - if(arr.getType().getTag() == TypeTags.TUPLE_TAG) { - if(!isOrderedType(arr.getType()) && function == null) { + if (arr.getType().getTag() == TypeTags.TUPLE_TAG) { + if (!isOrderedType(arr.getType()) && function == null) { throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INVALID_TYPE_TO_SORT), StringUtils.fromString("Valid Key function needed")); } - typeList = new HashSet<>(((BTupleType)arr.getType()).getTupleTypes()); - if(((BTupleType)arr.getType()).getRestType() != null) { - typeList.add(((BTupleType)arr.getType()).getRestType()); + typeList = new HashSet<>(((BTupleType) arr.getType()).getTupleTypes()); + if (((BTupleType) arr.getType()).getRestType() != null) { + typeList.add(((BTupleType) arr.getType()).getRestType()); } } Object[][] sortArr = new Object[arr.size()][2]; @@ -73,7 +74,7 @@ public static BArray sort(BArray arr, Object direction, Object func) { } } mergesort(sortArr, sortArrClone, 0, sortArr.length - 1, direction.toString()); - if(arr.getType().getTag() == TypeTags.TUPLE_TAG) { + if (arr.getType().getTag() == TypeTags.TUPLE_TAG) { sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType( TypeCreator.createUnionType(typeList.stream().toList()))); } else { diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java index 5c707e5f7bca..b67db20b69b4 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java @@ -29,7 +29,11 @@ import io.ballerina.runtime.internal.types.BFiniteType; import io.ballerina.runtime.internal.types.BTupleType; -import java.util.*; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; public class SortUtils { @@ -49,12 +53,12 @@ public static boolean isOrderedType(Type type) { // Union contains only the nil type. return true; } - if(!isOrderedType(firstTypeInUnion)) { + if (!isOrderedType(firstTypeInUnion)) { return false; } for (Type memType : memberTypes) { memType = TypeUtils.getImpliedType(memType); - if(!isOrderedType(memType) || isDifferentOrderedType(memType, firstTypeInUnion)) { + if (!isOrderedType(memType) || isDifferentOrderedType(memType, firstTypeInUnion)) { return false; } } @@ -63,8 +67,10 @@ public static boolean isOrderedType(Type type) { return isOrderedType(((BArrayType) type).getElementType()); case TypeTags.TUPLE_TAG: List tupleTypes = ((BTupleType) type).getTupleTypes(); - if (((BTupleType) type).getRestType() != null) tupleTypes.add(((BTupleType) type).getRestType()); - if(!isOrderedType(tupleTypes.get(0))) { + if (((BTupleType) type).getRestType() != null) { + tupleTypes.add(((BTupleType) type).getRestType()); + } + if (!isOrderedType(tupleTypes.get(0))) { return false; } for (Type memType : tupleTypes) { @@ -89,7 +95,7 @@ public static Type getTypeWithEffectiveIntersectionTypes(Type bType) { Type type = TypeUtils.getReferredType(bType); Type effectiveType = null; if (type.getTag() == TypeTags.INTERSECTION_TAG) { - effectiveType = ((IntersectionType)type).getEffectiveType(); + effectiveType = ((IntersectionType) type).getEffectiveType(); type = effectiveType; } @@ -122,7 +128,7 @@ public static boolean checkValueSpaceHasSameType(BFiniteType finiteType, Type ty TypeUtils.getType(finiteType.getValueSpace().iterator().next())); } for (Object expr : finiteType.getValueSpace()) { - if(isDifferentOrderedType(TypeUtils.getType(expr), baseType)) { + if (isDifferentOrderedType(TypeUtils.getType(expr), baseType)) { return false; } } @@ -135,7 +141,7 @@ public static boolean isDifferentOrderedType(Type source, Type target) { if (source.getTag() == TypeTags.NULL_TAG || target.getTag() == TypeTags.NULL_TAG) { return false; } - if(checkIfDifferent(source)) { + if (checkIfDifferent(source)) { return true; } return !TypeChecker.checkIsType(source, target); From bafd0e9b8d75122e570174d22d24ca67f57c87cb Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Tue, 20 Aug 2024 15:51:41 +0530 Subject: [PATCH 12/23] Refactor code and add additional tests --- .../org/ballerinalang/langlib/array/Sort.java | 2 +- .../langlib/array/utils/SortUtils.java | 52 +------------------ .../test/resources/test-src/arraylib_test.bal | 16 +++++- 3 files changed, 17 insertions(+), 53 deletions(-) diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java index fe0f4feb327c..9fd06104e25d 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java @@ -54,7 +54,7 @@ public static BArray sort(BArray arr, Object direction, Object func) { if (arr.getType().getTag() == TypeTags.TUPLE_TAG) { if (!isOrderedType(arr.getType()) && function == null) { throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INVALID_TYPE_TO_SORT), - StringUtils.fromString("Valid Key function needed")); + StringUtils.fromString("Valid key function required")); } typeList = new HashSet<>(((BTupleType) arr.getType()).getTupleTypes()); if (((BTupleType) arr.getType()).getRestType() != null) { diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java index b67db20b69b4..b75e23f38a63 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java @@ -19,8 +19,6 @@ package org.ballerinalang.langlib.array.utils; import io.ballerina.runtime.api.TypeTags; -import io.ballerina.runtime.api.creators.TypeCreator; -import io.ballerina.runtime.api.types.IntersectionType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.utils.TypeUtils; @@ -30,9 +28,7 @@ import io.ballerina.runtime.internal.types.BTupleType; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Objects; import java.util.Set; public class SortUtils { @@ -46,9 +42,8 @@ public static boolean isOrderedType(Type type) { return true; } Set memberTypes = new HashSet<>(unionType.getMemberTypes()); - Type firstTypeInUnion = getTypeWithEffectiveIntersectionTypes(TypeUtils.getImpliedType( - memberTypes.stream().filter(m -> m.getTag() != TypeTags.NULL_TAG).findFirst(). - orElse(memberTypes.iterator().next()))); + Type firstTypeInUnion = TypeUtils.getImpliedType(memberTypes.stream().findFirst(). + orElse(memberTypes.iterator().next())); if (firstTypeInUnion.getTag() == TypeTags.NULL_TAG) { // Union contains only the nil type. return true; @@ -91,36 +86,6 @@ public static boolean isOrderedType(Type type) { } } - public static Type getTypeWithEffectiveIntersectionTypes(Type bType) { - Type type = TypeUtils.getReferredType(bType); - Type effectiveType = null; - if (type.getTag() == TypeTags.INTERSECTION_TAG) { - effectiveType = ((IntersectionType) type).getEffectiveType(); - type = effectiveType; - } - - if (type.getTag() != TypeTags.UNION_TAG) { - return Objects.requireNonNullElse(effectiveType, bType); - } - - LinkedHashSet members = new LinkedHashSet<>(); - boolean hasDifferentMember = false; - - for (Type memberType : ((UnionType) type).getMemberTypes()) { - effectiveType = getTypeWithEffectiveIntersectionTypes(memberType); - effectiveType = TypeUtils.getImpliedType(effectiveType); - if (effectiveType != memberType) { - hasDifferentMember = true; - } - members.add(effectiveType); - } - - if (hasDifferentMember) { - return TypeCreator.createUnionType(members.stream().toList()); - } - return bType; - } - public static boolean checkValueSpaceHasSameType(BFiniteType finiteType, Type type) { Type baseType = TypeUtils.getImpliedType(type); if (baseType.getTag() == TypeTags.FINITE_TYPE_TAG) { @@ -141,9 +106,6 @@ public static boolean isDifferentOrderedType(Type source, Type target) { if (source.getTag() == TypeTags.NULL_TAG || target.getTag() == TypeTags.NULL_TAG) { return false; } - if (checkIfDifferent(source)) { - return true; - } return !TypeChecker.checkIsType(source, target); } @@ -154,14 +116,4 @@ public static boolean isSimpleBasicType(int tag) { default -> tag >= TypeTags.INT_TAG && tag <= TypeTags.CHAR_STRING_TAG; }; } - - public static boolean checkIfDifferent(Type s) { - return switch (s.getTag()) { - case TypeTags.TYPE_REFERENCED_TYPE_TAG, TypeTags.ANY_TAG, TypeTags.ANYDATA_TAG, TypeTags.MAP_TAG, - TypeTags.FUTURE_TAG, TypeTags.XML_TAG, TypeTags.JSON_TAG, TypeTags.OBJECT_TYPE_TAG, - TypeTags.RECORD_TYPE_TAG, TypeTags.STREAM_TAG, TypeTags.TABLE_TAG, TypeTags.INVOKABLE_TAG, - TypeTags.ERROR_TAG -> true; - default -> false; - }; - } } diff --git a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal index 0a276f2c8e77..08a11fd2eb3b 100644 --- a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal +++ b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal @@ -1957,18 +1957,30 @@ function testSort10() { assertValueEquality(sortedTup6, []); } +type Grade2 1|15|"B"; +type Grade3 15|17|Grade3[]; +type Grade4 (Grade2|int)|Grade3; + function testSortNegative() { [int, float] tup1 = [5, 7.3]; [int|float, float] tup2 = [5, 7.3]; [Grade, Student] tup3 = ["A", {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}]; [15|17, 15|17|21, 15|17|"hello"] tup4 = [15, 21, 17]; - anydata[][] items = [tup1, tup2, tup3, tup4]; + [int, Grade2] tup5 = [56, 1]; + [Student|int, int] tup6 = [{id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}, 7]; + [Grade3, int] tup7 = [17, 15]; + [Grade4, Grade3] tup8 = [1, 15]; + [(readonly & Person2 & Student2)|int, int] tup9 = [{id: 16158, name: "Arun", age: 12, average: 89.9, school: "JHC"}, 15]; + [((int|byte)|float), int] tup10 = [1, 15]; + [()|(), int] tup11 = [(),67]; + [json, json] tup12 = [{"abc":"defg"}, {"abc":"hello"}]; + anydata[][] items = [tup1, tup2, tup3, tup4, tup5, tup6, tup7, tup8, tup9, tup10, tup11, tup12]; foreach anydata[] item in items { any|error res = trap function:call(array:sort, item); assertTrue(res is error); if(res is error) { assertValueEquality("{ballerina/lang.array}SortOperationError", res.message()); - assertValueEquality("Valid Key function needed", checkpanic res.detail()["message"]); + assertValueEquality("Valid key function required", checkpanic res.detail()["message"]); } } } From a24620d966c835f29fd0f70ef2ca8ae260c92298 Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Tue, 20 Aug 2024 16:05:43 +0530 Subject: [PATCH 13/23] Remove unused TypePair class --- .../langlib/array/utils/TypePair.java | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java deleted file mode 100644 index 3b0b130c3cba..000000000000 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/TypePair.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.ballerinalang.langlib.array.utils; - -import io.ballerina.runtime.api.types.Type; - -import java.util.Objects; - -public class TypePair { - Type sourceType; - Type targetType; - - public TypePair(Type sourceType, Type targetType) { - this.sourceType = sourceType; - this.targetType = targetType; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof TypePair other)) { - return false; - } - - return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType); - } - - @Override - public int hashCode() { - return Objects.hash(sourceType, targetType); - } -} From c5daaea654d92b306868ce09652d183a764da99f Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Fri, 23 Aug 2024 11:04:38 +0530 Subject: [PATCH 14/23] Add additional tests and refactor code --- .../org/ballerinalang/langlib/array/Sort.java | 21 +- .../langlib/array/utils/SortUtils.java | 27 ++ .../langlib/test/LangLibArrayTest.java | 1 + .../test/resources/test-src/arraylib_test.bal | 316 ++++++++---------- 4 files changed, 179 insertions(+), 186 deletions(-) diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java index 9fd06104e25d..8f6f9864b2b3 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java @@ -49,17 +49,12 @@ public class Sort { public static BArray sort(BArray arr, Object direction, Object func) { BArray sortedArray; + Type arrType = arr.getType(); BFunctionPointer function = (BFunctionPointer) func; - Set typeList = new HashSet<>(); - if (arr.getType().getTag() == TypeTags.TUPLE_TAG) { - if (!isOrderedType(arr.getType()) && function == null) { - throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INVALID_TYPE_TO_SORT), - StringUtils.fromString("Valid key function required")); - } - typeList = new HashSet<>(((BTupleType) arr.getType()).getTupleTypes()); - if (((BTupleType) arr.getType()).getRestType() != null) { - typeList.add(((BTupleType) arr.getType()).getRestType()); - } + // Check if the array type is an Ordered type, otherwise a key function is mandatory + if (!isOrderedType(arrType) && function == null) { + throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INVALID_TYPE_TO_SORT), + StringUtils.fromString("Valid key function required")); } Object[][] sortArr = new Object[arr.size()][2]; Object[][] sortArrClone = new Object[arr.size()][2]; @@ -74,7 +69,11 @@ public static BArray sort(BArray arr, Object direction, Object func) { } } mergesort(sortArr, sortArrClone, 0, sortArr.length - 1, direction.toString()); - if (arr.getType().getTag() == TypeTags.TUPLE_TAG) { + if (arrType.getTag() == TypeTags.TUPLE_TAG) { + Set typeList = new HashSet<>(((BTupleType) arrType).getTupleTypes()); + if (((BTupleType) arrType).getRestType() != null) { + typeList.add(((BTupleType) arrType).getRestType()); + } sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType( TypeCreator.createUnionType(typeList.stream().toList()))); } else { diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java index b75e23f38a63..bbc4d101f09e 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java @@ -31,8 +31,18 @@ import java.util.List; import java.util.Set; +/** + * A utility class containing methods needed for the sort operation on tuples and arrays + * + * @since 2201.10.0 + */ public class SortUtils { + /** + * Check if the provided type is an Ordered type. + * @param type type to be checked. + * @return true if type is Ordered, false otherwise. + */ public static boolean isOrderedType(Type type) { type = TypeUtils.getImpliedType(type); switch (type.getTag()) { @@ -86,6 +96,12 @@ public static boolean isOrderedType(Type type) { } } + /** + * Check if the values space of the provided finite type belongs to the value space of the given type + * @param finiteType finite type to be checked. + * @param type type to be checked against. + * @return true if the finite type belongs to the same value space, false otherwise. + */ public static boolean checkValueSpaceHasSameType(BFiniteType finiteType, Type type) { Type baseType = TypeUtils.getImpliedType(type); if (baseType.getTag() == TypeTags.FINITE_TYPE_TAG) { @@ -100,6 +116,12 @@ public static boolean checkValueSpaceHasSameType(BFiniteType finiteType, Type ty return true; } + /** + * Check whether a given type is different to a target type. + * @param source type to check. + * @param target type to compare with. + * @return true if the source type does not belong to the target type, false otherwise. + */ public static boolean isDifferentOrderedType(Type source, Type target) { source = TypeUtils.getImpliedType(source); target = TypeUtils.getImpliedType(target); @@ -109,6 +131,11 @@ public static boolean isDifferentOrderedType(Type source, Type target) { return !TypeChecker.checkIsType(source, target); } + /** + * Check whether the given type tag belongs to a simple basic type. + * @param tag type tag to check. + * @return true if the tag belongs to a simple basic type, false otherwise. + */ public static boolean isSimpleBasicType(int tag) { return switch (tag) { case TypeTags.BYTE_TAG, TypeTags.FLOAT_TAG, TypeTags.DECIMAL_TAG, TypeTags.BOOLEAN_TAG, TypeTags.NULL_TAG -> diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java index 4d45141c2969..2f9335e8127a 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java @@ -563,6 +563,7 @@ public Object[] testFunctions() { "testSort8", "testSort9", "testSort10", + "testSort11", "testSortNegative", "testReadOnlyArrayFilter", "testTupleFilter", diff --git a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal index 08a11fd2eb3b..e460ef601899 100644 --- a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal +++ b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal @@ -988,28 +988,18 @@ function testSort1() { return s.id; }); - assertValueEquality(sortedArr[0].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); - assertValueEquality(sortedArr[1].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedArr[2].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedArr[3].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedArr[4].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedArr[0], studentArr[1]); + assertValueEquality(sortedArr[1], studentArr[3]); + assertValueEquality(sortedArr[2], studentArr[4]); + assertValueEquality(sortedArr[3], studentArr[2]); + assertValueEquality(sortedArr[4], studentArr[0]); assertFalse(studentArr == sortedArr); - assertValueEquality(sortedTup[0].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); - assertValueEquality(sortedTup[1].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedTup[2].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedTup[3].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedTup[4].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedTup[0], studentTup[1]); + assertValueEquality(sortedTup[1], studentTup[3]); + assertValueEquality(sortedTup[2], studentTup[4]); + assertValueEquality(sortedTup[3], studentTup[2]); + assertValueEquality(sortedTup[4], studentTup[0]); assertFalse(studentArr == sortedTup); Student[] sortedArr2 = studentArr.sort(array:DESCENDING, isolated function(Student s) returns string? { @@ -1020,28 +1010,18 @@ function testSort1() { return s.fname; }); - assertValueEquality(sortedArr2[0].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedArr2[1].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedArr2[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedArr2[3].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedArr2[4].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedArr2[0], studentArr[3]); + assertValueEquality(sortedArr2[1], studentArr[4]); + assertValueEquality(sortedArr2[2], studentArr[2]); + assertValueEquality(sortedArr2[3], studentArr[0]); + assertValueEquality(sortedArr2[4], studentArr[1]); assertFalse(studentArr == sortedArr2); - assertValueEquality(sortedTup2[0].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedTup2[1].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedTup2[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedTup2[3].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedTup2[4].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedTup2[0], studentTup[3]); + assertValueEquality(sortedTup2[1], studentTup[4]); + assertValueEquality(sortedTup2[2], studentTup[2]); + assertValueEquality(sortedTup2[3], studentTup[0]); + assertValueEquality(sortedTup2[4], studentTup[1]); assertFalse(studentArr == sortedArr2); Student[] sortedArr3 = studentArr.sort(array:ASCENDING, isolated function(Student s) returns float? { @@ -1052,27 +1032,17 @@ function testSort1() { return s.fee; }); - assertValueEquality(sortedArr3[0].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); - assertValueEquality(sortedArr3[1].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedArr3[2].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedArr3[3].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedArr3[4].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - - assertValueEquality(sortedTup3[0].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); - assertValueEquality(sortedTup3[1].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedTup3[2].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedTup3[3].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedTup3[4].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedArr3[0], studentArr[1]); + assertValueEquality(sortedArr3[1], studentArr[4]); + assertValueEquality(sortedArr3[2], studentArr[0]); + assertValueEquality(sortedArr3[3], studentArr[3]); + assertValueEquality(sortedArr3[4], studentArr[2]); + + assertValueEquality(sortedTup3[0], studentTup[1]); + assertValueEquality(sortedTup3[1], studentTup[4]); + assertValueEquality(sortedTup3[2], studentTup[0]); + assertValueEquality(sortedTup3[3], studentTup[3]); + assertValueEquality(sortedTup3[4], studentTup[2]); Student[] sortedArr4 = studentArr.sort(array:ASCENDING, isolated function(Student s) returns decimal { return s.impact; @@ -1082,42 +1052,27 @@ function testSort1() { return s.impact; }); - assertValueEquality(sortedArr4[0].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedArr4[1].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedArr4[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedArr4[3].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedArr4[4].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); - - assertValueEquality(sortedTup4[0].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedTup4[1].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedTup4[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedTup4[3].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedTup4[4].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedArr4[0], studentArr[0]); + assertValueEquality(sortedArr4[1], studentArr[3]); + assertValueEquality(sortedArr4[2], studentArr[2]); + assertValueEquality(sortedArr4[3], studentArr[4]); + assertValueEquality(sortedArr4[4], studentArr[1]); + + assertValueEquality(sortedTup4[0], studentTup[0]); + assertValueEquality(sortedTup4[1], studentTup[3]); + assertValueEquality(sortedTup4[2], studentTup[2]); + assertValueEquality(sortedTup4[3], studentTup[4]); + assertValueEquality(sortedTup4[4], studentTup[1]); Student[] sortedArr5 = sortedArr4.sort(array:ASCENDING, isolated function(Student s) returns boolean { return s.isUndergrad; }); - assertValueEquality(sortedArr5[0].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedArr5[1].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedArr5[2].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); - assertValueEquality(sortedArr5[3].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedArr5[4].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedArr5[0], studentArr[3]); + assertValueEquality(sortedArr5[1], studentArr[4]); + assertValueEquality(sortedArr5[2], studentArr[1]); + assertValueEquality(sortedArr5[3], studentArr[0]); + assertValueEquality(sortedArr5[4], studentArr[2]); assertFalse(sortedArr4 == sortedArr5); assertValueEquality(getStudentList(), studentArr); // no change to original array @@ -1268,16 +1223,16 @@ function testSort4() { return [val[1], 5.2]; }); - assertValueEquality(sortedArr[0].toString(), "[\"C\",2]"); - assertValueEquality(sortedArr[1].toString(), "[\"A+\",2]"); - assertValueEquality(sortedArr[2].toString(), "[\"A-\",3]"); - assertValueEquality(sortedArr[3].toString(), "[\"B\",3]"); + assertValueEquality(sortedArr[0], grades[3]); + assertValueEquality(sortedArr[1], grades[0]); + assertValueEquality(sortedArr[2], grades[1]); + assertValueEquality(sortedArr[3], grades[2]); assertValueEquality([["A+", 2], ["A-", 3], ["B", 3], ["C", 2]], grades); // no change to original array - assertValueEquality(sortedTup[0].toString(), "[\"C\",2]"); - assertValueEquality(sortedTup[1].toString(), "[\"A+\",2]"); - assertValueEquality(sortedTup[2].toString(), "[\"A-\",3]"); - assertValueEquality(sortedTup[3].toString(), "[\"B\",3]"); + assertValueEquality(sortedTup[0], gradesTup[3]); + assertValueEquality(sortedTup[1], gradesTup[0]); + assertValueEquality(sortedTup[2], gradesTup[1]); + assertValueEquality(sortedTup[3], gradesTup[2]); assertValueEquality([["A+", 2], ["A-", 3], ["B", 3], ["C", 2]], gradesTup); // no change to original array } @@ -1293,28 +1248,18 @@ function testSort5() { return getFullName(s.id, s.fname); }); - assertValueEquality(sortedArr[0].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedArr[1].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedArr[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedArr[3].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedArr[4].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedArr[0], studentArr[4]); + assertValueEquality(sortedArr[1], studentArr[3]); + assertValueEquality(sortedArr[2], studentArr[2]); + assertValueEquality(sortedArr[3], studentArr[0]); + assertValueEquality(sortedArr[4], studentArr[1]); assertValueEquality(getStudentList(), studentArr); // no change to original array - assertValueEquality(sortedTup[0].toString(), - "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); - assertValueEquality(sortedTup[1].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); - assertValueEquality(sortedTup[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedTup[3].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedTup[4].toString(), - "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedTup[0], studentTup[4]); + assertValueEquality(sortedTup[1], studentTup[3]); + assertValueEquality(sortedTup[2], studentTup[2]); + assertValueEquality(sortedTup[3], studentTup[0]); + assertValueEquality(sortedTup[4], studentTup[1]); assertValueEquality(getStudentListForTuples(), studentTup); // no change to original array } @@ -1360,22 +1305,22 @@ function testSort6() { return (); }); - assertValueEquality(sortedArr.toString(), - "[{\"k\":\"Bar\"},true,1,2.0,3,12.09,32,90,100,\"AA\",[\"BB\",true]]"); + assertValueEquality(sortedArr, + [>{"k": "Bar"},true,1,2.0,3,12.09,32,90,100,"AA",["BB",true]]); assertValueEquality([90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]], arr); - assertValueEquality(sortedTup.toString(), - "[{\"k\":\"Bar\"},true,1,2.0,3,12.09,32,90,100,\"AA\",[\"BB\",true]]"); + assertValueEquality(sortedTup, + [>{"k": "Bar"},true,1,2.0,3,12.09,32,90,100,"AA",["BB",true]]); assertValueEquality([90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]], tup); string?[] arr2 = ["Hello", "World!", (), "from", "Ballerina"]; [(string?)...] tup2 = ["Hello", "World!", (), "from", "Ballerina"]; string?[] sortedArr2 = arr2.sort(); - assertValueEquality(sortedArr2.toString(), "[\"Ballerina\",\"Hello\",\"World!\",\"from\",null]"); + assertValueEquality(sortedArr2, ["Ballerina","Hello","World!","from",null]); string?[] sortedTup2 = tup2.sort(); - assertValueEquality(sortedTup2.toString(), "[\"Ballerina\",\"Hello\",\"World!\",\"from\",null]"); + assertValueEquality(sortedTup2, ["Ballerina","Hello","World!","from",null]); Obj obj1 = new Obj(1, 1); Obj obj2 = new Obj(1, 2); @@ -1410,16 +1355,16 @@ function testSort6() { return i; }); - assertValueEquality(sortedArr4.toString(), "[0,1,3,7,9,21]"); - assertValueEquality(sortedTup4.toString(), "[0,1,3,7,9,21]"); + assertValueEquality(sortedArr4, [0,1,3,7,9,21]); + assertValueEquality(sortedTup4, [0,1,3,7,9,21]); int[] arr5 = [2, 0, 12, 1, 23, 3, 100, 55]; [int...] tup5 = [2, 0, 12, 1, 23, 3, 100, 55]; int[] sortedArr5 = arr5.sort(array:DESCENDING); int[] sortedTup5 = tup5.sort(array:DESCENDING); - assertValueEquality(sortedArr5.toString(), "[100,55,23,12,3,2,1,0]"); - assertValueEquality(sortedTup5.toString(), "[100,55,23,12,3,2,1,0]"); + assertValueEquality(sortedArr5, [100,55,23,12,3,2,1,0]); + assertValueEquality(sortedTup5, [100,55,23,12,3,2,1,0]); string?[] sortedArr6 = arr2.sort(array:DESCENDING, isolated function(string? s) returns string?[]? { if (s is string) { @@ -1435,8 +1380,8 @@ function testSort6() { return (); }); - assertValueEquality(sortedArr6.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); - assertValueEquality(sortedTup6.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); + assertValueEquality(sortedArr6, ["from","World!","Hello","Ballerina",null]); + assertValueEquality(sortedTup6, ["from","World!","Hello","Ballerina",null]); string?[] sortedArr7 = arr2.sort(array:ASCENDING, isolated function(string? s) returns string?[] { if (s is string) { @@ -1452,13 +1397,13 @@ function testSort6() { return ["W", "A"]; }); - assertValueEquality(sortedArr7.toString(), "[\"Ballerina\",\"Hello\",null,\"World!\",\"from\"]"); - assertValueEquality(sortedTup7.toString(), "[\"Ballerina\",\"Hello\",null,\"World!\",\"from\"]"); + assertValueEquality(sortedArr7, ["Ballerina","Hello",null,"World!","from"]); + assertValueEquality(sortedTup7, ["Ballerina","Hello",null,"World!","from"]); int[] sortedArr8 = arr5.sort(array:ASCENDING, ()); int[] sortedTup8 = tup5.sort(array:ASCENDING, ()); - assertValueEquality(sortedArr8.toString(), "[0,1,2,3,12,23,55,100]"); - assertValueEquality(sortedTup8.toString(), "[0,1,2,3,12,23,55,100]"); + assertValueEquality(sortedArr8, [0,1,2,3,12,23,55,100]); + assertValueEquality(sortedTup8, [0,1,2,3,12,23,55,100]); Grade[] arr6 = ["A+", "B+", "C", "F", "A-", "C", "A+", "B"]; [Grade...] tup6 = ["A+", "B+", "C", "F", "A-", "C", "A+", "B"]; @@ -1471,9 +1416,9 @@ function testSort6() { return grade; }); - assertValueEquality(sortedArr9.toString(), "[\"F\",\"C\",\"C\",\"B+\",\"B\",\"A-\",\"A+\",\"A+\"]"); + assertValueEquality(sortedArr9, ["F","C","C","B+","B","A-","A+","A+"]); assertValueEquality(["A+", "B+", "C", "F", "A-", "C", "A+", "B"], arr6); // no change to arr6 - assertValueEquality(sortedTup9.toString(), "[\"F\",\"C\",\"C\",\"B+\",\"B\",\"A-\",\"A+\",\"A+\"]"); + assertValueEquality(sortedTup9, ["F","C","C","B+","B","A-","A+","A+"]); assertValueEquality(["A+", "B+", "C", "F", "A-", "C", "A+", "B"], arr6); // no change to tup6 Student s1 = {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}; @@ -1499,35 +1444,29 @@ function testSort6() { } }); - assertValueEquality(sortedArr10[0].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedArr10[1].toString(), "Anne"); - assertValueEquality(sortedArr10[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedArr10[3].toString(), "Frank"); - assertValueEquality(sortedArr10[4].toString(), "James"); - assertValueEquality(sortedArr10[5].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedArr10[0], s1); + assertValueEquality(sortedArr10[1], "Anne"); + assertValueEquality(sortedArr10[2], s2); + assertValueEquality(sortedArr10[3], "Frank"); + assertValueEquality(sortedArr10[4], "James"); + assertValueEquality(sortedArr10[5], s3); assertValueEquality(["Anne", s3, s1, "James", "Frank", s2], arr7); // no change to arr7 - assertValueEquality(sortedTup10[0].toString(), - "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); - assertValueEquality(sortedTup10[1].toString(), "Anne"); - assertValueEquality(sortedTup10[2].toString(), - "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); - assertValueEquality(sortedTup10[3].toString(), "Frank"); - assertValueEquality(sortedTup10[4].toString(), "James"); - assertValueEquality(sortedTup10[5].toString(), - "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedTup10[0], s1); + assertValueEquality(sortedTup10[1], "Anne"); + assertValueEquality(sortedTup10[2], s2); + assertValueEquality(sortedTup10[3], "Frank"); + assertValueEquality(sortedTup10[4], "James"); + assertValueEquality(sortedTup10[5], s3); assertValueEquality(["Anne", s3, s1, "James", "Frank", s2], tup7); // no change to tup7 int[] sortedArr11 = array:sort(arr5); [int...] sortedTup11 = array:sort(tup5); - assertValueEquality(sortedArr11.toString(), "[0,1,2,3,12,23,55,100]"); + assertValueEquality(sortedArr11, [0,1,2,3,12,23,55,100]); assertValueEquality([2, 0, 12, 1, 23, 3, 100, 55], arr5); // no change to arr5 assertValueEquality([0, 1, 2, 3, 12, 23, 55, 100], sortedArr8); // no change to sortedArr8 - assertValueEquality(sortedTup11.toString(), "[0,1,2,3,12,23,55,100]"); + assertValueEquality(sortedTup11, [0,1,2,3,12,23,55,100]); assertValueEquality([2, 0, 12, 1, 23, 3, 100, 55], tup5); // no change to tup5 assertValueEquality([0, 1, 2, 3, 12, 23, 55, 100], sortedTup8); // no change to sortedTup8 @@ -1539,16 +1478,16 @@ function testSort6() { return i; }); - assertValueEquality(sortedArr12.toString(), "[21,9,7,3,1,0]"); + assertValueEquality(sortedArr12, [21,9,7,3,1,0]); assertValueEquality([1, 9, 3, 21, 0, 7], arr4); // no change to arr4 - assertValueEquality(sortedTup12.toString(), "[21,9,7,3,1,0]"); + assertValueEquality(sortedTup12, [21,9,7,3,1,0]); assertValueEquality([1, 9, 3, 21, 0, 7], tup4); // no change to tup4 string?[] sortedArr13 = array:sort(arr2, array:DESCENDING); string?[] sortedTup13 = array:sort(tup2, array:DESCENDING); - assertValueEquality(sortedArr13.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); - assertValueEquality(sortedTup13.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); + assertValueEquality(sortedArr13, ["from", "World!", "Hello", "Ballerina", null]); + assertValueEquality(sortedTup13, ["from", "World!", "Hello", "Ballerina", null]); } function testSort7() { @@ -1755,18 +1694,16 @@ function testSort9() { strings:Char[] sortedArr = arr.sort(array:DESCENDING); strings:Char[] sortedTup = tup.sort(array:DESCENDING); - assertValueEquality(sortedArr.toString(), "[\"s\",\"b\",\"a\",\"Z\",\"M\"]"); - assertValueEquality(sortedTup.toString(), "[\"s\",\"b\",\"a\",\"Z\",\"M\"]"); + assertValueEquality(sortedArr, ["s","b","a","Z","M"]); + assertValueEquality(sortedTup, ["s","b","a","Z","M"]); int[] arr2 = [4294967295, 4194967295, 4294967290, 4284967295, 3294967295, 1294967295]; [int...] tup2 = [4294967295, 4194967295, 4294967290, 4284967295, 3294967295, 1294967295]; int[] sortedArr2 = arr2.sort(); int[] sortedTup2 = tup2.sort(); - assertValueEquality(sortedArr2.toString(), - "[1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]"); - assertValueEquality(sortedTup2.toString(), - "[1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]"); + assertValueEquality(sortedArr2, [1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]); + assertValueEquality(sortedTup2, [1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]); ints:Signed32[] arr3 = [2147483647, -2147483648, 2147483637, -1147483648, -2137483648, 1147483647]; [ints:Signed32...] tup3 = [2147483647, -2147483648, 2147483637, -1147483648, -2137483648, 1147483647]; @@ -1859,7 +1796,7 @@ function testSort9() { [ints:Unsigned16...] tup7 = [450, 65335, 0, 12, 65535, 12500, 4]; ints:Unsigned16[] sortedArr7 = arr7.sort(array:DESCENDING); - ints:Unsigned16[] sortedTup7 = arr7.sort(array:DESCENDING); + ints:Unsigned16[] sortedTup7 = tup7.sort(array:DESCENDING); assertValueEquality(sortedArr7[0], 65535); assertValueEquality(sortedArr7[1], 65335); @@ -1907,8 +1844,8 @@ function testSort10() { int[] sortedArr = arr.sort(array:ASCENDING, (i) => i); int[] sortedTup = tup.sort(array:ASCENDING, (i) => i); - assertValueEquality(sortedArr.toString(), "[0,1,2,3,6,10]"); - assertValueEquality(sortedTup.toString(), "[0,1,2,3,6,10]"); + assertValueEquality(sortedArr, [0,1,2,3,6,10]); + assertValueEquality(sortedTup, [0,1,2,3,6,10]); final int methodInt1 = 2; var addFunc1 = isolated function(int funcInt1) returns (int) { @@ -1924,14 +1861,14 @@ function testSort10() { int[] sortedArr2 = arr.sort(array:DESCENDING, addFunc1); int[] sortedTup2 = tup.sort(array:DESCENDING, addFunc1); - assertValueEquality(sortedArr2.toString(), "[10,6,3,2,1,0]"); - assertValueEquality(sortedTup2.toString(), "[10,6,3,2,1,0]"); + assertValueEquality(sortedArr2, [10,6,3,2,1,0]); + assertValueEquality(sortedTup2, [10,6,3,2,1,0]); int[] sortedArr3 = array:sort(arr, array:ASCENDING, isolated function(int x) returns string[] => [x.toString(), "World"]); int[] sortedTup3 = array:sort(tup, array:ASCENDING, isolated function(int x) returns string[] => [x.toString(), "World"]); - assertValueEquality(sortedArr3.toString(), "[0,1,10,2,3,6]"); - assertValueEquality(sortedTup3.toString(), "[0,1,10,2,3,6]"); + assertValueEquality(sortedArr3, [0,1,10,2,3,6]); + assertValueEquality(sortedTup3, [0,1,10,2,3,6]); int[] sortedArr4 = arr.sort(array:DESCENDING, (i) => i.toString()); int[] sortedTup4 = tup.sort(array:DESCENDING, (i) => i.toString()); @@ -1961,6 +1898,35 @@ type Grade2 1|15|"B"; type Grade3 15|17|Grade3[]; type Grade4 (Grade2|int)|Grade3; +function testSort11() { + var keyFunc = isolated function((int|float|string|boolean) x) returns int { + if x is int { + return x; + } else if x is float { + return x; + }else if x is boolean{ + return 0; + }else { + return 100; + } + }; + + [int, float, string] tup1 = [7, 2.4, "Hello"]; + [int|float, float] tup2 = [89, 9.7]; + [boolean, string...] tup3 = [false, "Hello", "World"]; + [Grade2, Grade2, string, int...] tup4 = [1, 15, "Hello", 76, 89]; + + (int|float|string)[] sortedTup1 = tup1.sort("ascending", keyFunc); + (int|float)[] sortedTup2 = tup2.sort("descending", keyFunc); + (boolean|string)[] sortedTup3 = tup3.sort("descending", keyFunc); + (int|string)[] sortedTup4 = tup4.sort("descending", keyFunc); + + assertValueEquality(sortedTup1, [2.4, 7, "Hello"]); + assertValueEquality(sortedTup2, [89, 9.7]); + assertValueEquality(sortedTup3, ["Hello", "World", false]); + assertValueEquality(sortedTup4, ["Hello", 89, 76, 15, 1]); +} + function testSortNegative() { [int, float] tup1 = [5, 7.3]; [int|float, float] tup2 = [5, 7.3]; From d438418aeadc77ac1206e9bfc83daaf5f582a65a Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Fri, 23 Aug 2024 15:26:47 +0530 Subject: [PATCH 15/23] Fix checkstyle issue --- .../java/org/ballerinalang/langlib/array/utils/SortUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java index bbc4d101f09e..1d8afe63f8a3 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java @@ -32,7 +32,7 @@ import java.util.Set; /** - * A utility class containing methods needed for the sort operation on tuples and arrays + * A utility class containing methods needed for the sort operation on tuples and arrays. * * @since 2201.10.0 */ @@ -97,7 +97,7 @@ public static boolean isOrderedType(Type type) { } /** - * Check if the values space of the provided finite type belongs to the value space of the given type + * Check if the values space of the provided finite type belongs to the value space of the given type. * @param finiteType finite type to be checked. * @param type type to be checked against. * @return true if the finite type belongs to the same value space, false otherwise. From 5f118b816390f07e4e19f2f677907234a7348a78 Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Thu, 5 Sep 2024 11:29:35 +0530 Subject: [PATCH 16/23] Add suggestions from code review --- .../org/ballerinalang/langlib/array/Sort.java | 7 ++++--- .../langlib/array/utils/SortUtils.java | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java index 8f6f9864b2b3..2f80505d75f8 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java @@ -70,9 +70,10 @@ public static BArray sort(BArray arr, Object direction, Object func) { } mergesort(sortArr, sortArrClone, 0, sortArr.length - 1, direction.toString()); if (arrType.getTag() == TypeTags.TUPLE_TAG) { - Set typeList = new HashSet<>(((BTupleType) arrType).getTupleTypes()); - if (((BTupleType) arrType).getRestType() != null) { - typeList.add(((BTupleType) arrType).getRestType()); + BTupleType tupleType = (BTupleType) arrType; + Set typeList = new HashSet<>(tupleType.getTupleTypes()); + if (tupleType.getRestType() != null) { + typeList.add(tupleType.getRestType()); } sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType( TypeCreator.createUnionType(typeList.stream().toList()))); diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java index 1d8afe63f8a3..ac9b74eadb50 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java @@ -38,6 +38,11 @@ */ public class SortUtils { + /** + * A private constructor to avoid code coverage warnings. + */ + private SortUtils() {}; + /** * Check if the provided type is an Ordered type. * @param type type to be checked. @@ -71,9 +76,10 @@ public static boolean isOrderedType(Type type) { case TypeTags.ARRAY_TAG: return isOrderedType(((BArrayType) type).getElementType()); case TypeTags.TUPLE_TAG: - List tupleTypes = ((BTupleType) type).getTupleTypes(); - if (((BTupleType) type).getRestType() != null) { - tupleTypes.add(((BTupleType) type).getRestType()); + BTupleType tupleType = (BTupleType) type; + List tupleTypes = tupleType.getTupleTypes(); + if (tupleType.getRestType() != null) { + tupleTypes.add(tupleType.getRestType()); } if (!isOrderedType(tupleTypes.get(0))) { return false; @@ -85,9 +91,10 @@ public static boolean isOrderedType(Type type) { } return true; case TypeTags.FINITE_TYPE_TAG: - Set valSpace = ((BFiniteType) type).getValueSpace(); + BFiniteType finiteType = (BFiniteType) type; + Set valSpace = finiteType.getValueSpace(); Type baseExprType = TypeUtils.getType(valSpace.iterator().next()); - if (!checkValueSpaceHasSameType((BFiniteType) type, baseExprType)) { + if (!checkValueSpaceHasSameType(finiteType, baseExprType)) { return false; } return isOrderedType(baseExprType); @@ -97,7 +104,7 @@ public static boolean isOrderedType(Type type) { } /** - * Check if the values space of the provided finite type belongs to the value space of the given type. + * Check if the value space of the provided finite type belongs to the value space of the given type. * @param finiteType finite type to be checked. * @param type type to be checked against. * @return true if the finite type belongs to the same value space, false otherwise. From 60e89bfd43d79761795f4e15b78a70f9ae21d972 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Mon, 9 Sep 2024 15:39:58 +0530 Subject: [PATCH 17/23] add mapping readonly field tests --- .../MappingConstructorExprTest.java | 18 +++++ .../javainterop/basic/StaticMethodTest.java | 1 - ...leVsArrayReadonlyErrorConsistencyTest.java | 65 ------------------- ...s_array_readonly_violation_consistency.bal | 12 +++- ...onsistency_without_tuple_Update_method.bal | 10 ++- 5 files changed, 38 insertions(+), 68 deletions(-) delete mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java index b9ca6102648a..5727eeca2e41 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java @@ -38,6 +38,8 @@ public class MappingConstructorExprTest { private CompileResult inferRecordResult; private CompileResult spreadOpFieldResult; private CompileResult readOnlyFieldResult; + private CompileResult resultWithTupleUpdateMethod; + private CompileResult resultWithoutTupleUpdateMethod; @BeforeClass public void setup() { @@ -47,6 +49,10 @@ public void setup() { varNameFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/var_name_field.bal"); spreadOpFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/spread_op_field.bal"); readOnlyFieldResult = BCompileUtil.compile("test-src/expressions/mappingconstructor/readonly_field.bal"); + resultWithTupleUpdateMethod = + BCompileUtil.compile("test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal"); + resultWithoutTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/" + + "test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal"); } @Test(dataProvider = "mappingConstructorTests") @@ -379,6 +385,16 @@ public void testReadOnlyFields(String test) { BRunUtil.invoke(readOnlyFieldResult, test); } + @Test + public void testReadOnlyFields2() { + BRunUtil.invoke(resultWithTupleUpdateMethod, "testFrozenAnyArrayElementUpdate"); + } + + @Test + public void testReadOnlyFields3() { + BRunUtil.invoke(resultWithoutTupleUpdateMethod, "testFrozenAnyArrayElementUpdate"); + } + @DataProvider(name = "readOnlyFieldTests") public Object[][] readOnlyFieldTests() { return new Object[][] { @@ -502,5 +518,7 @@ public void tearDown() { inferRecordResult = null; spreadOpFieldResult = null; readOnlyFieldResult = null; + resultWithTupleUpdateMethod = null; + resultWithoutTupleUpdateMethod = null; } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java index 8151a11969a7..539cabb346a2 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/StaticMethodTest.java @@ -172,7 +172,6 @@ public void testCreateRawDetails() { expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" + "\"cannot update 'readonly' field 'name' in record of type 'Details & readonly'\".*") public void testCreateDetails() { - BRunUtil.invoke(result, "testCreateDetails"); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java deleted file mode 100644 index 0dbf845b3687..000000000000 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/readonly/TupleVsArrayReadonlyErrorConsistencyTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.ballerinalang.test.types.readonly; - -import org.ballerinalang.test.BCompileUtil; -import org.ballerinalang.test.BRunUtil; -import org.ballerinalang.test.CompileResult; -import org.ballerinalang.test.exceptions.BLangTestException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -/** - * Tests for the readonly violation error consistency between BTuple type and BRecord type. - * - * @since 2201.10.0 - */ -public class TupleVsArrayReadonlyErrorConsistencyTest { - private CompileResult resultWithTupleUpdateMethod; - private CompileResult resultWithoutTupleUpdateMethod; - - @BeforeClass - public void setup() { - resultWithTupleUpdateMethod = - BCompileUtil.compile("test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal"); - resultWithoutTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/" + - "test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal"); - } - - @Test(expectedExceptions = BLangTestException.class, - expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" + - "\"cannot update 'readonly' field 'name' in record of type '\\(Employee & readonly\\)'\".*") - public void testWithTupleUpdateMethod() { - BRunUtil.invoke(resultWithTupleUpdateMethod, "testFrozenAnyArrayElementUpdate"); - } - - @Test(expectedExceptions = BLangTestException.class, - expectedExceptionsMessageRegExp = "error: \\{ballerina/lang.map}InherentTypeViolation \\{\"message\":" + - "\"cannot update 'readonly' field 'name' in record of type 'Employee & readonly'\".*") - public void testWithoutTupleUpdateMethod() { - BRunUtil.invoke(resultWithoutTupleUpdateMethod, "testFrozenAnyArrayElementUpdate"); - } - - @AfterClass - public void tearDown() { - resultWithTupleUpdateMethod = null; - resultWithoutTupleUpdateMethod = null; - } -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal index 5f5ab46b1259..f4704921d802 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal @@ -14,12 +14,22 @@ // specific language governing permissions and limitations // under the License. +import ballerina/test; + type Employee record {| int id; string name; |}; function testFrozenAnyArrayElementUpdate() returns error? { + error? actualError = trap frozenAnyArrayElementUpdate(); + test:assertTrue(actualError is error); + test:assertEquals((actualError).message(), "{ballerina/lang.map}InherentTypeViolation"); + test:assertEquals((actualError).detail()["message"], + "cannot update 'readonly' field 'name' in record of type '(Employee & readonly)'"); +} + +function frozenAnyArrayElementUpdate() returns error? { Employee e1 = {name: "Em", id: 1000}; anydata[] i1 = [e1]; anydata[] i2 = i1.cloneReadOnly(); @@ -28,7 +38,7 @@ function testFrozenAnyArrayElementUpdate() returns error? { return (); } -function testFrozenTupleUpdate() { +function frozenTupleUpdate() { Employee e1 = {name: "Em", id: 1000}; [int, Employee] t1 = [1, e1]; [int, Employee] t2 = t1.cloneReadOnly(); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal index 3cceed237e09..2232cd830e04 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal @@ -19,7 +19,7 @@ type Employee record {| string name; |}; -function testFrozenAnyArrayElementUpdate() returns error? { +function frozenAnyArrayElementUpdate() returns error? { Employee e1 = {name: "Em", id: 1000}; anydata[] i1 = [e1]; anydata[] i2 = i1.cloneReadOnly(); @@ -27,3 +27,11 @@ function testFrozenAnyArrayElementUpdate() returns error? { e2["name"] = "Zee"; return (); } + +function testFrozenAnyArrayElementUpdate() returns error? { + error? actualError = trap frozenAnyArrayElementUpdate(); + test:assertTrue(actualError is error); + test:assertEquals((actualError).message(), "{ballerina/lang.map}InherentTypeViolation"); + test:assertEquals((actualError).detail()["message"], + "cannot update 'readonly' field 'name' in record of type '(Employee & readonly)'"); +} From fab7ee879d70af200e4b2aaf4ac193608901c533 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 10 Sep 2024 11:14:38 +0530 Subject: [PATCH 18/23] Fix the error message in readonly field tests --- ...donly_violation_consistency_without_tuple_Update_method.bal | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal index 2232cd830e04..b04fe3c9e75a 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +import ballerina/test; type Employee record {| int id; @@ -33,5 +34,5 @@ function testFrozenAnyArrayElementUpdate() returns error? { test:assertTrue(actualError is error); test:assertEquals((actualError).message(), "{ballerina/lang.map}InherentTypeViolation"); test:assertEquals((actualError).detail()["message"], - "cannot update 'readonly' field 'name' in record of type '(Employee & readonly)'"); + "cannot update 'readonly' field 'name' in record of type 'Employee & readonly'"); } From bf6d35dc05ced5496484237b8506e8190df267a3 Mon Sep 17 00:00:00 2001 From: Felix Schnabel Date: Wed, 18 Sep 2024 17:04:06 +0200 Subject: [PATCH 19/23] Declare missing Service usage and remove exports non existing modules --- .../src/main/java/module-info.java | 14 +++++++------- .../ballerina-lang/src/main/java/module-info.java | 3 +++ .../langserver-core/src/main/java/module-info.java | 3 ++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/module-info.java b/bvm/ballerina-runtime/src/main/java/module-info.java index de8f45222601..32a43bd94043 100644 --- a/bvm/ballerina-runtime/src/main/java/module-info.java +++ b/bvm/ballerina-runtime/src/main/java/module-info.java @@ -1,4 +1,5 @@ module io.ballerina.runtime { + uses io.ballerina.runtime.api.launch.LaunchListener; requires java.xml; requires org.apache.commons.text; requires axiom.api; @@ -44,23 +45,22 @@ io.ballerina.lang.floatingpoint, io.ballerina.lang.internal, io.ballerina.lang.function, io.ballerina.lang.regexp, io.ballerina.runtime.profiler; exports io.ballerina.runtime.internal.commons to io.ballerina.lang.value; - exports io.ballerina.runtime.internal.launch to io.ballerina.testerina.runtime, io.ballerina.packerina, - ballerina.test.listener, io.ballerina.cli, org.ballerinalang.debugadapter.runtime; - exports io.ballerina.runtime.internal.scheduling to io.ballerina.cli.utils, io.ballerina.java, + exports io.ballerina.runtime.internal.launch to io.ballerina.testerina.runtime, ballerina.test.listener, + io.ballerina.cli, org.ballerinalang.debugadapter.runtime; + exports io.ballerina.runtime.internal.scheduling to io.ballerina.java, io.ballerina.lang.array, io.ballerina.lang.error, io.ballerina.lang.internal, io.ballerina.lang.map, io.ballerina.lang.table, io.ballerina.lang.transaction, io.ballerina.lang.value, io.ballerina.lang.xml, - io.ballerina.log.api, io.ballerina.testerina.core, io.ballerina.testerina.runtime, io.ballerina.shell, + io.ballerina.testerina.core, io.ballerina.testerina.runtime, io.ballerina.shell, org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function, io.ballerina.runtime.profiler; exports io.ballerina.runtime.internal.util to io.ballerina.testerina.runtime, io.ballerina.lang, io.ballerina.lang.integer, io.ballerina.lang.floatingpoint, io.ballerina.lang.array, io.ballerina.lang.table, io.ballerina.java, io.ballerina.lang.map, io.ballerina.lang.string, io.ballerina.lang.xml, io.ballerina.lang.bool, io.ballerina.lang.error, io.ballerina.lang.internal, - io.ballerina.lang.value, io.ballerina.auth, io.ballerina.runtime.api, io.ballerina.cli.utils, - io.ballerina.cli; + io.ballerina.lang.value, io.ballerina.cli; exports io.ballerina.runtime.internal.errors to io.ballerina.lang.value, io.ballerina.lang.integer, io.ballerina.java, io.ballerina.lang.internal, io.ballerina.lang.array, io.ballerina.lang.bool, io.ballerina.lang.floatingpoint, io.ballerina.lang.map, io.ballerina.lang.string, io.ballerina.lang.table, - io.ballerina.lang.xml, io.ballerina.testerina.core, io.ballerina.cli.utils, io.ballerina.cli, + io.ballerina.lang.xml, io.ballerina.testerina.core, io.ballerina.cli, io.ballerina.lang.decimal, org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function, io.ballerina.lang.regexp; exports io.ballerina.runtime.internal.values to io.ballerina.testerina.core, io.ballerina.testerina.runtime, diff --git a/compiler/ballerina-lang/src/main/java/module-info.java b/compiler/ballerina-lang/src/main/java/module-info.java index f3ae030b12a9..bf773acd7296 100644 --- a/compiler/ballerina-lang/src/main/java/module-info.java +++ b/compiler/ballerina-lang/src/main/java/module-info.java @@ -1,6 +1,9 @@ module io.ballerina.lang { uses io.ballerina.projects.plugins.CompilerPlugin; uses io.ballerina.projects.buildtools.CodeGeneratorTool; + uses org.ballerinalang.spi.CompilerBackendCodeGenerator; + uses org.ballerinalang.compiler.plugins.CompilerPlugin; + uses org.ballerinalang.spi.EmbeddedExecutor; requires java.compiler; requires com.google.gson; requires java.xml; diff --git a/language-server/modules/langserver-core/src/main/java/module-info.java b/language-server/modules/langserver-core/src/main/java/module-info.java index deac82e07835..a2ad981981ed 100644 --- a/language-server/modules/langserver-core/src/main/java/module-info.java +++ b/language-server/modules/langserver-core/src/main/java/module-info.java @@ -11,6 +11,7 @@ uses org.ballerinalang.langserver.eventsync.EventPublisher; uses org.ballerinalang.langserver.commons.codeaction.spi.DiagnosticBasedCodeActionProvider; uses org.ballerinalang.langserver.commons.codeaction.spi.RangeBasedCodeActionProvider; + uses org.ballerinalang.langserver.commons.completion.spi.BallerinaCompletionProvider; exports org.ballerinalang.langserver; exports org.ballerinalang.langserver.references; exports org.ballerinalang.langserver.common.utils; @@ -20,7 +21,7 @@ exports org.ballerinalang.langserver.extensions; exports org.ballerinalang.langserver.config; exports org.ballerinalang.langserver.telemetry; - exports org.ballerinalang.langserver.util to io.ballerina.language.server.simulator; + exports org.ballerinalang.langserver.util; exports org.ballerinalang.langserver.codeaction to io.ballerina.datamapper; requires io.ballerina.diagram.util; requires io.ballerina.formatter.core; From 47f707437372939e6864383c24e81e2afb5f2500 Mon Sep 17 00:00:00 2001 From: ravinperera00 Date: Thu, 26 Sep 2024 15:35:55 +0530 Subject: [PATCH 20/23] Add suggestions from code review --- .../src/main/java/org/ballerinalang/langlib/array/Sort.java | 2 +- .../java/org/ballerinalang/langlib/array/utils/SortUtils.java | 2 +- .../langlib-test/src/test/resources/test-src/arraylib_test.bal | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java index 2f80505d75f8..f1191a84b226 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java @@ -54,7 +54,7 @@ public static BArray sort(BArray arr, Object direction, Object func) { // Check if the array type is an Ordered type, otherwise a key function is mandatory if (!isOrderedType(arrType) && function == null) { throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INVALID_TYPE_TO_SORT), - StringUtils.fromString("Valid key function required")); + StringUtils.fromString("valid key function required")); } Object[][] sortArr = new Object[arr.size()][2]; Object[][] sortArrClone = new Object[arr.size()][2]; diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java index ac9b74eadb50..daf1ec39a765 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java @@ -34,7 +34,7 @@ /** * A utility class containing methods needed for the sort operation on tuples and arrays. * - * @since 2201.10.0 + * @since 2201.11.0 */ public class SortUtils { diff --git a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal index e460ef601899..01e0d094abaa 100644 --- a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal +++ b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal @@ -1946,7 +1946,7 @@ function testSortNegative() { assertTrue(res is error); if(res is error) { assertValueEquality("{ballerina/lang.array}SortOperationError", res.message()); - assertValueEquality("Valid key function required", checkpanic res.detail()["message"]); + assertValueEquality("valid key function required", checkpanic res.detail()["message"]); } } } From bb59e29a2693113c73ee9e6b0ec9bc57e8980dd5 Mon Sep 17 00:00:00 2001 From: Felix Schnabel Date: Thu, 3 Oct 2024 16:13:02 +0200 Subject: [PATCH 21/23] Fix escaping of spaces in the classpath --- distribution/zip/jballerina-tools/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distribution/zip/jballerina-tools/build.gradle b/distribution/zip/jballerina-tools/build.gradle index 71399d71d782..7a85dab15bba 100644 --- a/distribution/zip/jballerina-tools/build.gradle +++ b/distribution/zip/jballerina-tools/build.gradle @@ -390,7 +390,7 @@ tasks.register('pathingJar', Jar) { doFirst { manifest { attributes "Class-Path": configurations.docerina.files.collect { - it.toURL().toString().replaceFirst("file:/", "/") + it.toURI().toString() }.join(' ') } } From f4b21aa502fff0892610981c282fd90eee7c8c7c Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Fri, 4 Oct 2024 14:27:01 +0530 Subject: [PATCH 22/23] Update test file names in mapping constructor tests --- .../mappingconstructor/MappingConstructorExprTest.java | 2 +- .../test_tuple_vs_array_readonly_violation_consistency.bal | 5 +++-- ...array_readonly_violation_without_tuple_update_method.bal} | 0 3 files changed, 4 insertions(+), 3 deletions(-) rename tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/{test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal => test_tuple_vs_array_readonly_violation_without_tuple_update_method.bal} (100%) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java index 5727eeca2e41..9a2c6b1f7a23 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/expressions/mappingconstructor/MappingConstructorExprTest.java @@ -52,7 +52,7 @@ public void setup() { resultWithTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal"); resultWithoutTupleUpdateMethod = BCompileUtil.compile("test-src/types/readonly/" + - "test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal"); + "test_tuple_vs_array_readonly_violation_without_tuple_update_method.bal"); } @Test(dataProvider = "mappingConstructorTests") diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal index f4704921d802..ed4ca4cfc3fe 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency.bal @@ -24,8 +24,9 @@ type Employee record {| function testFrozenAnyArrayElementUpdate() returns error? { error? actualError = trap frozenAnyArrayElementUpdate(); test:assertTrue(actualError is error); - test:assertEquals((actualError).message(), "{ballerina/lang.map}InherentTypeViolation"); - test:assertEquals((actualError).detail()["message"], + error e = actualError; + test:assertEquals(e.message(), "{ballerina/lang.map}InherentTypeViolation"); + test:assertEquals(e.detail()["message"], "cannot update 'readonly' field 'name' in record of type '(Employee & readonly)'"); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_without_tuple_update_method.bal similarity index 100% rename from tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_consistency_without_tuple_Update_method.bal rename to tests/jballerina-unit-test/src/test/resources/test-src/types/readonly/test_tuple_vs_array_readonly_violation_without_tuple_update_method.bal From b6680710c5e04b81d3ed4b362de6b98acbef6867 Mon Sep 17 00:00:00 2001 From: Gimantha Bandara Date: Mon, 7 Oct 2024 10:13:23 +0530 Subject: [PATCH 23/23] Revert "Add checks and logic to support `sort` operation for tuples at runtime" --- .../src/main/java/module-info.java | 2 +- .../org/ballerinalang/langlib/array/Sort.java | 36 +- .../langlib/array/utils/SortUtils.java | 153 ----- .../langlib/test/LangLibArrayTest.java | 2 - .../langlib/test/LangLibTupleTest.java | 3 +- .../test/resources/test-src/arraylib_test.bal | 558 +++--------------- 6 files changed, 104 insertions(+), 650 deletions(-) delete mode 100644 langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java diff --git a/bvm/ballerina-runtime/src/main/java/module-info.java b/bvm/ballerina-runtime/src/main/java/module-info.java index 4f8ed3c3a3d8..de8f45222601 100644 --- a/bvm/ballerina-runtime/src/main/java/module-info.java +++ b/bvm/ballerina-runtime/src/main/java/module-info.java @@ -68,7 +68,7 @@ io.ballerina.lang.function, io.ballerina.lang.regexp, io.ballerina.lang.value, io.ballerina.lang.internal, io.ballerina.lang.array; exports io.ballerina.runtime.internal.configurable to io.ballerina.lang.internal; exports io.ballerina.runtime.internal.types to io.ballerina.lang.typedesc, io.ballerina.testerina.runtime, - org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function, io.ballerina.lang.regexp, io.ballerina.testerina.core, io.ballerina.lang.array; + org.ballerinalang.debugadapter.runtime, io.ballerina.lang.function, io.ballerina.lang.regexp, io.ballerina.testerina.core; exports io.ballerina.runtime.observability.metrics.noop; exports io.ballerina.runtime.observability.tracer.noop; exports io.ballerina.runtime.internal.regexp; diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java index c7e4b3a67b23..9b20bcc78b6f 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Sort.java @@ -18,12 +18,10 @@ package org.ballerinalang.langlib.array; -import io.ballerina.runtime.api.TypeTags; import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.creators.TypeCreator; import io.ballerina.runtime.api.creators.ValueCreator; -import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BFunctionPointer; @@ -31,15 +29,11 @@ import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.internal.ValueComparisonUtils; import io.ballerina.runtime.internal.scheduling.Scheduler; -import io.ballerina.runtime.internal.types.BTupleType; - -import java.util.HashSet; -import java.util.Set; import static io.ballerina.runtime.api.constants.RuntimeConstants.ARRAY_LANG_LIB; import static io.ballerina.runtime.internal.errors.ErrorReasons.INVALID_TYPE_TO_SORT; import static io.ballerina.runtime.internal.errors.ErrorReasons.getModulePrefixedReason; -import static org.ballerinalang.langlib.array.utils.SortUtils.isOrderedType; +import static org.ballerinalang.langlib.array.utils.ArrayUtils.checkIsArrayOnlyOperation; /** * Native implementation of lang.array:sort((any|error)[], direction, function). @@ -52,16 +46,12 @@ private Sort() { } public static BArray sort(BArray arr, Object direction, Object func) { - BArray sortedArray; - Type arrType = arr.getType(); + checkIsArrayOnlyOperation(TypeUtils.getImpliedType(arr.getType()), "sort()"); BFunctionPointer function = (BFunctionPointer) func; - // Check if the array type is an Ordered type, otherwise a key function is mandatory - if (!isOrderedType(arrType) && function == null) { - throw ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, INVALID_TYPE_TO_SORT), - StringUtils.fromString("valid key function required")); - } + Object[][] sortArr = new Object[arr.size()][2]; Object[][] sortArrClone = new Object[arr.size()][2]; + if (function != null) { for (int i = 0; i < arr.size(); i++) { sortArr[i][0] = function.call(new Object[]{Scheduler.getStrand(), arr.get(i), true}); @@ -72,21 +62,15 @@ public static BArray sort(BArray arr, Object direction, Object func) { sortArr[i][0] = sortArr[i][1] = arr.get(i); } } + mergesort(sortArr, sortArrClone, 0, sortArr.length - 1, direction.toString()); - if (arrType.getTag() == TypeTags.TUPLE_TAG) { - BTupleType tupleType = (BTupleType) arrType; - Set typeList = new HashSet<>(tupleType.getTupleTypes()); - if (tupleType.getRestType() != null) { - typeList.add(tupleType.getRestType()); - } - sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType( - TypeCreator.createUnionType(typeList.stream().toList()))); - } else { - sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType(arr.getElementType())); - } + + BArray sortedArray = ValueCreator.createArrayValue(TypeCreator.createArrayType(arr.getElementType())); + for (int k = 0; k < sortArr.length; k++) { sortedArray.add(k, sortArr[k][1]); } + return sortedArray; } diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java deleted file mode 100644 index daf1ec39a765..000000000000 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/SortUtils.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.ballerinalang.langlib.array.utils; - -import io.ballerina.runtime.api.TypeTags; -import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.UnionType; -import io.ballerina.runtime.api.utils.TypeUtils; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.types.BArrayType; -import io.ballerina.runtime.internal.types.BFiniteType; -import io.ballerina.runtime.internal.types.BTupleType; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * A utility class containing methods needed for the sort operation on tuples and arrays. - * - * @since 2201.11.0 - */ -public class SortUtils { - - /** - * A private constructor to avoid code coverage warnings. - */ - private SortUtils() {}; - - /** - * Check if the provided type is an Ordered type. - * @param type type to be checked. - * @return true if type is Ordered, false otherwise. - */ - public static boolean isOrderedType(Type type) { - type = TypeUtils.getImpliedType(type); - switch (type.getTag()) { - case TypeTags.UNION_TAG: - UnionType unionType = (UnionType) type; - if (unionType.isCyclic()) { - return true; - } - Set memberTypes = new HashSet<>(unionType.getMemberTypes()); - Type firstTypeInUnion = TypeUtils.getImpliedType(memberTypes.stream().findFirst(). - orElse(memberTypes.iterator().next())); - if (firstTypeInUnion.getTag() == TypeTags.NULL_TAG) { - // Union contains only the nil type. - return true; - } - if (!isOrderedType(firstTypeInUnion)) { - return false; - } - for (Type memType : memberTypes) { - memType = TypeUtils.getImpliedType(memType); - if (!isOrderedType(memType) || isDifferentOrderedType(memType, firstTypeInUnion)) { - return false; - } - } - return true; - case TypeTags.ARRAY_TAG: - return isOrderedType(((BArrayType) type).getElementType()); - case TypeTags.TUPLE_TAG: - BTupleType tupleType = (BTupleType) type; - List tupleTypes = tupleType.getTupleTypes(); - if (tupleType.getRestType() != null) { - tupleTypes.add(tupleType.getRestType()); - } - if (!isOrderedType(tupleTypes.get(0))) { - return false; - } - for (Type memType : tupleTypes) { - if (!isOrderedType(memType) || isDifferentOrderedType(memType, tupleTypes.get(0))) { - return false; - } - } - return true; - case TypeTags.FINITE_TYPE_TAG: - BFiniteType finiteType = (BFiniteType) type; - Set valSpace = finiteType.getValueSpace(); - Type baseExprType = TypeUtils.getType(valSpace.iterator().next()); - if (!checkValueSpaceHasSameType(finiteType, baseExprType)) { - return false; - } - return isOrderedType(baseExprType); - default: - return isSimpleBasicType(type.getTag()); - } - } - - /** - * Check if the value space of the provided finite type belongs to the value space of the given type. - * @param finiteType finite type to be checked. - * @param type type to be checked against. - * @return true if the finite type belongs to the same value space, false otherwise. - */ - public static boolean checkValueSpaceHasSameType(BFiniteType finiteType, Type type) { - Type baseType = TypeUtils.getImpliedType(type); - if (baseType.getTag() == TypeTags.FINITE_TYPE_TAG) { - return checkValueSpaceHasSameType((BFiniteType) baseType, - TypeUtils.getType(finiteType.getValueSpace().iterator().next())); - } - for (Object expr : finiteType.getValueSpace()) { - if (isDifferentOrderedType(TypeUtils.getType(expr), baseType)) { - return false; - } - } - return true; - } - - /** - * Check whether a given type is different to a target type. - * @param source type to check. - * @param target type to compare with. - * @return true if the source type does not belong to the target type, false otherwise. - */ - public static boolean isDifferentOrderedType(Type source, Type target) { - source = TypeUtils.getImpliedType(source); - target = TypeUtils.getImpliedType(target); - if (source.getTag() == TypeTags.NULL_TAG || target.getTag() == TypeTags.NULL_TAG) { - return false; - } - return !TypeChecker.checkIsType(source, target); - } - - /** - * Check whether the given type tag belongs to a simple basic type. - * @param tag type tag to check. - * @return true if the tag belongs to a simple basic type, false otherwise. - */ - public static boolean isSimpleBasicType(int tag) { - return switch (tag) { - case TypeTags.BYTE_TAG, TypeTags.FLOAT_TAG, TypeTags.DECIMAL_TAG, TypeTags.BOOLEAN_TAG, TypeTags.NULL_TAG -> - true; - default -> tag >= TypeTags.INT_TAG && tag <= TypeTags.CHAR_STRING_TAG; - }; - } -} diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java index 2f9335e8127a..8de3b049c988 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java @@ -563,8 +563,6 @@ public Object[] testFunctions() { "testSort8", "testSort9", "testSort10", - "testSort11", - "testSortNegative", "testReadOnlyArrayFilter", "testTupleFilter", "testTupleReverse", diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java index 0baa6a41c5fa..96e425c14df6 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibTupleTest.java @@ -113,7 +113,8 @@ public void testRemove() { BRunUtil.invoke(compileResult, "testRemove"); } - @Test + @Test(expectedExceptions = RuntimeException.class, + expectedExceptionsMessageRegExp = ".*error: \\{ballerina/lang.array\\}OperationNotSupported.*") public void testSort() { BRunUtil.invoke(compileResult, "testSort"); } diff --git a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal index 01e0d094abaa..264abcef5534 100644 --- a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal +++ b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal @@ -964,119 +964,88 @@ function getStudentList() returns Student[] { return studentList; } -function getStudentListForTuples() returns [Student...] { - Student s1 = {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}; - Student s2 = {id: 20, fname: (), fee: 2000.56, impact: 0.45, isUndergrad: false}; - Student s3 = {id: 2, fname: "Dan", fee: (), impact: 0.3, isUndergrad: true}; - Student s4 = {id: 10, fname: "Kate", fee: (0.0 / 0.0), impact: 0.146, isUndergrad: false}; - Student s5 = {id: 3, fname: "Kate", fee: 5000.56, impact: 0.4, isUndergrad: false}; - - [Student...] studentList = [s1, s2, s3, s4, s5]; - - return studentList; -} - function testSort1() { Student[] studentArr = getStudentList(); - [Student...] studentTup = getStudentListForTuples(); Student[] sortedArr = studentArr.sort(array:DESCENDING, isolated function(Student s) returns int { return s.id; }); - Student[] sortedTup = studentTup.sort(array:DESCENDING, isolated function(Student s) returns int { - return s.id; - }); - - assertValueEquality(sortedArr[0], studentArr[1]); - assertValueEquality(sortedArr[1], studentArr[3]); - assertValueEquality(sortedArr[2], studentArr[4]); - assertValueEquality(sortedArr[3], studentArr[2]); - assertValueEquality(sortedArr[4], studentArr[0]); + assertValueEquality(sortedArr[0].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedArr[1].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedArr[2].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedArr[3].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedArr[4].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); assertFalse(studentArr == sortedArr); - assertValueEquality(sortedTup[0], studentTup[1]); - assertValueEquality(sortedTup[1], studentTup[3]); - assertValueEquality(sortedTup[2], studentTup[4]); - assertValueEquality(sortedTup[3], studentTup[2]); - assertValueEquality(sortedTup[4], studentTup[0]); - assertFalse(studentArr == sortedTup); - Student[] sortedArr2 = studentArr.sort(array:DESCENDING, isolated function(Student s) returns string? { return s.fname; }); - Student[] sortedTup2 = studentTup.sort(array:DESCENDING, isolated function(Student s) returns string? { - return s.fname; - }); - - assertValueEquality(sortedArr2[0], studentArr[3]); - assertValueEquality(sortedArr2[1], studentArr[4]); - assertValueEquality(sortedArr2[2], studentArr[2]); - assertValueEquality(sortedArr2[3], studentArr[0]); - assertValueEquality(sortedArr2[4], studentArr[1]); - assertFalse(studentArr == sortedArr2); - - assertValueEquality(sortedTup2[0], studentTup[3]); - assertValueEquality(sortedTup2[1], studentTup[4]); - assertValueEquality(sortedTup2[2], studentTup[2]); - assertValueEquality(sortedTup2[3], studentTup[0]); - assertValueEquality(sortedTup2[4], studentTup[1]); + assertValueEquality(sortedArr2[0].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedArr2[1].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedArr2[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedArr2[3].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedArr2[4].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); assertFalse(studentArr == sortedArr2); Student[] sortedArr3 = studentArr.sort(array:ASCENDING, isolated function(Student s) returns float? { return s.fee; }); - Student[] sortedTup3 = studentTup.sort(array:ASCENDING, isolated function(Student s) returns float? { - return s.fee; - }); - - assertValueEquality(sortedArr3[0], studentArr[1]); - assertValueEquality(sortedArr3[1], studentArr[4]); - assertValueEquality(sortedArr3[2], studentArr[0]); - assertValueEquality(sortedArr3[3], studentArr[3]); - assertValueEquality(sortedArr3[4], studentArr[2]); - - assertValueEquality(sortedTup3[0], studentTup[1]); - assertValueEquality(sortedTup3[1], studentTup[4]); - assertValueEquality(sortedTup3[2], studentTup[0]); - assertValueEquality(sortedTup3[3], studentTup[3]); - assertValueEquality(sortedTup3[4], studentTup[2]); + assertValueEquality(sortedArr3[0].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedArr3[1].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedArr3[2].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedArr3[3].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedArr3[4].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); Student[] sortedArr4 = studentArr.sort(array:ASCENDING, isolated function(Student s) returns decimal { return s.impact; }); - Student[] sortedTup4 = studentTup.sort(array:ASCENDING, isolated function(Student s) returns decimal { - return s.impact; - }); - - assertValueEquality(sortedArr4[0], studentArr[0]); - assertValueEquality(sortedArr4[1], studentArr[3]); - assertValueEquality(sortedArr4[2], studentArr[2]); - assertValueEquality(sortedArr4[3], studentArr[4]); - assertValueEquality(sortedArr4[4], studentArr[1]); - - assertValueEquality(sortedTup4[0], studentTup[0]); - assertValueEquality(sortedTup4[1], studentTup[3]); - assertValueEquality(sortedTup4[2], studentTup[2]); - assertValueEquality(sortedTup4[3], studentTup[4]); - assertValueEquality(sortedTup4[4], studentTup[1]); + assertValueEquality(sortedArr4[0].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedArr4[1].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedArr4[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedArr4[3].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedArr4[4].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); Student[] sortedArr5 = sortedArr4.sort(array:ASCENDING, isolated function(Student s) returns boolean { return s.isUndergrad; }); - assertValueEquality(sortedArr5[0], studentArr[3]); - assertValueEquality(sortedArr5[1], studentArr[4]); - assertValueEquality(sortedArr5[2], studentArr[1]); - assertValueEquality(sortedArr5[3], studentArr[0]); - assertValueEquality(sortedArr5[4], studentArr[2]); + assertValueEquality(sortedArr5[0].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedArr5[1].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedArr5[2].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); + assertValueEquality(sortedArr5[3].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedArr5[4].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); assertFalse(sortedArr4 == sortedArr5); assertValueEquality(getStudentList(), studentArr); // no change to original array - assertValueEquality(getStudentListForTuples(), studentTup); } function testSort2() { @@ -1207,7 +1176,6 @@ function testSort3() returns int[] { function testSort4() { [Grade, int][] grades = [["A+", 2], ["A-", 3], ["B", 3], ["C", 2]]; - [[Grade, int]...] gradesTup = [["A+", 2], ["A-", 3], ["B", 3], ["C", 2]]; [Grade, int][] sortedArr = grades.sort(array:ASCENDING, isolated function([Grade, int] val) returns float[] { if (val[0] == "A+") { @@ -1216,51 +1184,31 @@ function testSort4() { return [val[1], 5.2]; }); - [Grade, int][] sortedTup = gradesTup.sort(array:ASCENDING, isolated function([Grade, int] val) returns float[] { - if (val[0] == "A+") { - return [val[1], 6.5]; - } - return [val[1], 5.2]; - }); - - assertValueEquality(sortedArr[0], grades[3]); - assertValueEquality(sortedArr[1], grades[0]); - assertValueEquality(sortedArr[2], grades[1]); - assertValueEquality(sortedArr[3], grades[2]); + assertValueEquality(sortedArr[0].toString(), "[\"C\",2]"); + assertValueEquality(sortedArr[1].toString(), "[\"A+\",2]"); + assertValueEquality(sortedArr[2].toString(), "[\"A-\",3]"); + assertValueEquality(sortedArr[3].toString(), "[\"B\",3]"); assertValueEquality([["A+", 2], ["A-", 3], ["B", 3], ["C", 2]], grades); // no change to original array - - assertValueEquality(sortedTup[0], gradesTup[3]); - assertValueEquality(sortedTup[1], gradesTup[0]); - assertValueEquality(sortedTup[2], gradesTup[1]); - assertValueEquality(sortedTup[3], gradesTup[2]); - assertValueEquality([["A+", 2], ["A-", 3], ["B", 3], ["C", 2]], gradesTup); // no change to original array } function testSort5() { Student[] studentArr = getStudentList(); - [Student...] studentTup = getStudentListForTuples(); Student[] sortedArr = studentArr.sort(array:DESCENDING, isolated function(Student s) returns string? { return getFullName(s.id, s.fname); }); - Student[] sortedTup = studentTup.sort(array:DESCENDING, isolated function(Student s) returns string? { - return getFullName(s.id, s.fname); - }); - - assertValueEquality(sortedArr[0], studentArr[4]); - assertValueEquality(sortedArr[1], studentArr[3]); - assertValueEquality(sortedArr[2], studentArr[2]); - assertValueEquality(sortedArr[3], studentArr[0]); - assertValueEquality(sortedArr[4], studentArr[1]); + assertValueEquality(sortedArr[0].toString(), + "{\"id\":3,\"fname\":\"Kate\",\"fee\":5000.56,\"impact\":0.4,\"isUndergrad\":false}"); + assertValueEquality(sortedArr[1].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); + assertValueEquality(sortedArr[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedArr[3].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedArr[4].toString(), + "{\"id\":20,\"fname\":null,\"fee\":2000.56,\"impact\":0.45,\"isUndergrad\":false}"); assertValueEquality(getStudentList(), studentArr); // no change to original array - - assertValueEquality(sortedTup[0], studentTup[4]); - assertValueEquality(sortedTup[1], studentTup[3]); - assertValueEquality(sortedTup[2], studentTup[2]); - assertValueEquality(sortedTup[3], studentTup[0]); - assertValueEquality(sortedTup[4], studentTup[1]); - assertValueEquality(getStudentListForTuples(), studentTup); // no change to original array } isolated function getFullName(int id, string? name) returns string? { @@ -1277,7 +1225,6 @@ type StringOrStudent string|Student; function testSort6() { anydata[] arr = [90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]]; - [anydata...] tup = [90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]]; anydata[] sortedArr = arr.sort(array:ASCENDING, isolated function(anydata a) returns int? { if (a is int) { @@ -1292,79 +1239,40 @@ function testSort6() { return (); }); - anydata[] sortedTup = tup.sort(array:ASCENDING, isolated function(anydata a) returns int? { - if (a is int) { - return a; - } else if (a is float) { - return a; - } else if (a is boolean) { - return 0; - } else if (a is map) { - return -1; - } - return (); - }); - - assertValueEquality(sortedArr, - [>{"k": "Bar"},true,1,2.0,3,12.09,32,90,100,"AA",["BB",true]]); + assertValueEquality(sortedArr.toString(), + "[{\"k\":\"Bar\"},true,1,2.0,3,12.09,32,90,100,\"AA\",[\"BB\",true]]"); assertValueEquality([90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]], arr); - assertValueEquality(sortedTup, - [>{"k": "Bar"},true,1,2.0,3,12.09,32,90,100,"AA",["BB",true]]); - assertValueEquality([90, 2.0, 1, true, 32, "AA", 12.09, 100, 3, >{"k": "Bar"}, ["BB", true]], tup); - string?[] arr2 = ["Hello", "World!", (), "from", "Ballerina"]; - [(string?)...] tup2 = ["Hello", "World!", (), "from", "Ballerina"]; string?[] sortedArr2 = arr2.sort(); - assertValueEquality(sortedArr2, ["Ballerina","Hello","World!","from",null]); - - string?[] sortedTup2 = tup2.sort(); - assertValueEquality(sortedTup2, ["Ballerina","Hello","World!","from",null]); + assertValueEquality(sortedArr2.toString(), "[\"Ballerina\",\"Hello\",\"World!\",\"from\",null]"); Obj obj1 = new Obj(1, 1); Obj obj2 = new Obj(1, 2); Obj obj3 = new Obj(1, 10); Obj[] arr3 = [obj1, obj2, obj3]; - [Obj...] tup3 = [obj1, obj2, obj3]; Obj[] sortedArr3 = arr3.sort(array:DESCENDING, isolated function(Obj obj) returns int { return obj.j; }); - Obj[] sortedTup3 = tup3.sort(array:DESCENDING, isolated function(Obj obj) returns int { - return obj.j; - }); - assertValueEquality(sortedArr3[0].j, 10); assertValueEquality(sortedArr3[1].j, 2); assertValueEquality(sortedArr3[2].j, 1); - assertValueEquality(sortedTup3[0].j, 10); - assertValueEquality(sortedTup3[1].j, 2); - assertValueEquality(sortedTup3[2].j, 1); - int[2]|int[] arr4 = [1, 9, 3, 21, 0, 7]; - [int, int]|[int...] tup4 = [1, 9, 3, 21, 0, 7]; int[2]|int[] sortedArr4 = arr4.sort(array:ASCENDING, isolated function(int i) returns int { return i; }); - int[2]|int[] sortedTup4 = tup4.sort(array:ASCENDING, isolated function(int i) returns int { - return i; - }); - - assertValueEquality(sortedArr4, [0,1,3,7,9,21]); - assertValueEquality(sortedTup4, [0,1,3,7,9,21]); + assertValueEquality(sortedArr4.toString(), "[0,1,3,7,9,21]"); int[] arr5 = [2, 0, 12, 1, 23, 3, 100, 55]; - [int...] tup5 = [2, 0, 12, 1, 23, 3, 100, 55]; int[] sortedArr5 = arr5.sort(array:DESCENDING); - int[] sortedTup5 = tup5.sort(array:DESCENDING); - assertValueEquality(sortedArr5, [100,55,23,12,3,2,1,0]); - assertValueEquality(sortedTup5, [100,55,23,12,3,2,1,0]); + assertValueEquality(sortedArr5.toString(), "[100,55,23,12,3,2,1,0]"); string?[] sortedArr6 = arr2.sort(array:DESCENDING, isolated function(string? s) returns string?[]? { if (s is string) { @@ -1373,15 +1281,7 @@ function testSort6() { return (); }); - string?[] sortedTup6 = tup2.sort(array:DESCENDING, isolated function(string? s) returns string?[]? { - if (s is string) { - return [s, "A"]; - } - return (); - }); - - assertValueEquality(sortedArr6, ["from","World!","Hello","Ballerina",null]); - assertValueEquality(sortedTup6, ["from","World!","Hello","Ballerina",null]); + assertValueEquality(sortedArr6.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); string?[] sortedArr7 = arr2.sort(array:ASCENDING, isolated function(string? s) returns string?[] { if (s is string) { @@ -1390,43 +1290,25 @@ function testSort6() { return ["W", "A"]; }); - string?[] sortedTup7 = tup2.sort(array:ASCENDING, isolated function(string? s) returns string?[] { - if (s is string) { - return [s, "A"]; - } - return ["W", "A"]; - }); - - assertValueEquality(sortedArr7, ["Ballerina","Hello",null,"World!","from"]); - assertValueEquality(sortedTup7, ["Ballerina","Hello",null,"World!","from"]); + assertValueEquality(sortedArr7.toString(), "[\"Ballerina\",\"Hello\",null,\"World!\",\"from\"]"); int[] sortedArr8 = arr5.sort(array:ASCENDING, ()); - int[] sortedTup8 = tup5.sort(array:ASCENDING, ()); - assertValueEquality(sortedArr8, [0,1,2,3,12,23,55,100]); - assertValueEquality(sortedTup8, [0,1,2,3,12,23,55,100]); + assertValueEquality(sortedArr8.toString(), "[0,1,2,3,12,23,55,100]"); Grade[] arr6 = ["A+", "B+", "C", "F", "A-", "C", "A+", "B"]; - [Grade...] tup6 = ["A+", "B+", "C", "F", "A-", "C", "A+", "B"]; Grade[] sortedArr9 = arr6.sort(array:DESCENDING, isolated function(Grade grade) returns string { return grade; }); - Grade[] sortedTup9 = arr6.sort(array:DESCENDING, isolated function(Grade grade) returns string { - return grade; - }); - - assertValueEquality(sortedArr9, ["F","C","C","B+","B","A-","A+","A+"]); + assertValueEquality(sortedArr9.toString(), "[\"F\",\"C\",\"C\",\"B+\",\"B\",\"A-\",\"A+\",\"A+\"]"); assertValueEquality(["A+", "B+", "C", "F", "A-", "C", "A+", "B"], arr6); // no change to arr6 - assertValueEquality(sortedTup9, ["F","C","C","B+","B","A-","A+","A+"]); - assertValueEquality(["A+", "B+", "C", "F", "A-", "C", "A+", "B"], arr6); // no change to tup6 Student s1 = {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}; Student s2 = {id: 2, fname: "Dan", fee: (), impact: 0.3, isUndergrad: true}; Student s3 = {id: 10, fname: "Kate", fee: (0.0 / 0.0), impact: 0.146, isUndergrad: false}; StringOrStudent[] arr7 = ["Anne", s3, s1, "James", "Frank", s2]; - [StringOrStudent...] tup7 = ["Anne", s3, s1, "James", "Frank", s2]; StringOrStudent[] sortedArr10 = arr7.sort(array:ASCENDING, isolated function(StringOrStudent sp) returns string? { if (sp is Student) { @@ -1436,58 +1318,31 @@ function testSort6() { } }); - StringOrStudent[] sortedTup10 = tup7.sort(array:ASCENDING, isolated function(StringOrStudent sp) returns string? { - if (sp is Student) { - return sp.fname; - } else { - return sp; - } - }); - - assertValueEquality(sortedArr10[0], s1); - assertValueEquality(sortedArr10[1], "Anne"); - assertValueEquality(sortedArr10[2], s2); - assertValueEquality(sortedArr10[3], "Frank"); - assertValueEquality(sortedArr10[4], "James"); - assertValueEquality(sortedArr10[5], s3); + assertValueEquality(sortedArr10[0].toString(), + "{\"id\":1,\"fname\":\"Amber\",\"fee\":10000.56,\"impact\":0.127,\"isUndergrad\":true}"); + assertValueEquality(sortedArr10[1].toString(), "Anne"); + assertValueEquality(sortedArr10[2].toString(), + "{\"id\":2,\"fname\":\"Dan\",\"fee\":null,\"impact\":0.3,\"isUndergrad\":true}"); + assertValueEquality(sortedArr10[3].toString(), "Frank"); + assertValueEquality(sortedArr10[4].toString(), "James"); + assertValueEquality(sortedArr10[5].toString(), + "{\"id\":10,\"fname\":\"Kate\",\"fee\":NaN,\"impact\":0.146,\"isUndergrad\":false}"); assertValueEquality(["Anne", s3, s1, "James", "Frank", s2], arr7); // no change to arr7 - assertValueEquality(sortedTup10[0], s1); - assertValueEquality(sortedTup10[1], "Anne"); - assertValueEquality(sortedTup10[2], s2); - assertValueEquality(sortedTup10[3], "Frank"); - assertValueEquality(sortedTup10[4], "James"); - assertValueEquality(sortedTup10[5], s3); - assertValueEquality(["Anne", s3, s1, "James", "Frank", s2], tup7); // no change to tup7 - int[] sortedArr11 = array:sort(arr5); - [int...] sortedTup11 = array:sort(tup5); - assertValueEquality(sortedArr11, [0,1,2,3,12,23,55,100]); + assertValueEquality(sortedArr11.toString(), "[0,1,2,3,12,23,55,100]"); assertValueEquality([2, 0, 12, 1, 23, 3, 100, 55], arr5); // no change to arr5 assertValueEquality([0, 1, 2, 3, 12, 23, 55, 100], sortedArr8); // no change to sortedArr8 - assertValueEquality(sortedTup11, [0,1,2,3,12,23,55,100]); - assertValueEquality([2, 0, 12, 1, 23, 3, 100, 55], tup5); // no change to tup5 - assertValueEquality([0, 1, 2, 3, 12, 23, 55, 100], sortedTup8); // no change to sortedTup8 - int[2]|int[] sortedArr12 = array:sort(arr4, array:DESCENDING, isolated function(int i) returns int { return i; }); - int[2]|int[] sortedTup12 = array:sort(tup4, array:DESCENDING, isolated function(int i) returns int { - return i; - }); - - assertValueEquality(sortedArr12, [21,9,7,3,1,0]); + assertValueEquality(sortedArr12.toString(), "[21,9,7,3,1,0]"); assertValueEquality([1, 9, 3, 21, 0, 7], arr4); // no change to arr4 - assertValueEquality(sortedTup12, [21,9,7,3,1,0]); - assertValueEquality([1, 9, 3, 21, 0, 7], tup4); // no change to tup4 - string?[] sortedArr13 = array:sort(arr2, array:DESCENDING); - string?[] sortedTup13 = array:sort(tup2, array:DESCENDING); - assertValueEquality(sortedArr13, ["from", "World!", "Hello", "Ballerina", null]); - assertValueEquality(sortedTup13, ["from", "World!", "Hello", "Ballerina", null]); + assertValueEquality(sortedArr13.toString(), "[\"from\",\"World!\",\"Hello\",\"Ballerina\",null]"); } function testSort7() { @@ -1512,29 +1367,7 @@ function testSort7() { [1.8, (0.0 / 0.0)] ]; - [(float?[])...] tup = [ - [1.8, 2.89, 5, 70, 90], - [(), 4], - [1.8, 2.89, 5, 70], - [(0.0 / 0.0), 9, 8, 10], - [ - 1.8, - 2.89, - 5, - 70, - () - ], - [1.8, 2.89, 5], - [1.8, 2.89, 4], - [1.8, 2.89], - [2.8, 2.89, 5, 70, 90], - [3], - [1.8, 2.89, 5, 70, (0.0 / 0.0)], - [1.8, (0.0 / 0.0)] - ]; - float?[][] sortedArr = arr.sort(array:DESCENDING); - float?[][] sortedTup = tup.sort(array:DESCENDING); assertValueEquality(sortedArr[0], [3.0]); assertValueEquality(sortedArr[1], [2.8, 2.89, 5.0, 70.0, 90.0]); @@ -1549,27 +1382,10 @@ function testSort7() { assertValueEquality(sortedArr[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); assertValueEquality(sortedArr[11], [(), 4.0]); - assertValueEquality(sortedTup[0], [3.0]); - assertValueEquality(sortedTup[1], [2.8, 2.89, 5.0, 70.0, 90.0]); - assertValueEquality(sortedTup[2], [1.8, 2.89, 5.0, 70.0, 90.0]); - assertValueEquality(sortedTup[3], [1.8, 2.89, 5.0, 70.0, (0.0 / 0.0)]); - assertValueEquality(sortedTup[4], [1.8, 2.89, 5.0, 70.0, ()]); - assertValueEquality(sortedTup[5], [1.8, 2.89, 5.0, 70.0]); - assertValueEquality(sortedTup[6], [1.8, 2.89, 5.0]); - assertValueEquality(sortedTup[7], [1.8, 2.89, 4.0]); - assertValueEquality(sortedTup[8], [1.8, 2.89]); - assertValueEquality(sortedTup[9], [1.8, (0.0 / 0.0)]); - assertValueEquality(sortedTup[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); - assertValueEquality(sortedTup[11], [(), 4.0]); - float?[][] sortedArr2 = arr.sort(array:ASCENDING, isolated function(float?[] x) returns float?[] { return x; }); - float?[][] sortedTup2 = tup.sort(array:ASCENDING, isolated function(float?[] x) returns float?[] { - return x; - }); - assertValueEquality(sortedArr2[0], [1.8, 2.89]); assertValueEquality(sortedArr2[1], [1.8, 2.89, 4.0]); assertValueEquality(sortedArr2[2], [1.8, 2.89, 5.0]); @@ -1583,50 +1399,24 @@ function testSort7() { assertValueEquality(sortedArr2[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); assertValueEquality(sortedArr2[11], [(), 4.0]); - assertValueEquality(sortedTup2[0], [1.8, 2.89]); - assertValueEquality(sortedTup2[1], [1.8, 2.89, 4.0]); - assertValueEquality(sortedTup2[2], [1.8, 2.89, 5.0]); - assertValueEquality(sortedTup2[3], [1.8, 2.89, 5.0, 70.0]); - assertValueEquality(sortedTup2[4], [1.8, 2.89, 5.0, 70.0, 90.0]); - assertValueEquality(sortedTup2[5], [1.8, 2.89, 5.0, 70.0, (0.0 / 0.0)]); - assertValueEquality(sortedTup2[6], [1.8, 2.89, 5.0, 70.0, ()]); - assertValueEquality(sortedTup2[7], [1.8, (0.0 / 0.0)]); - assertValueEquality(sortedTup2[8], [2.8, 2.89, 5.0, 70.0, 90.0]); - assertValueEquality(sortedTup2[9], [3.0]); - assertValueEquality(sortedTup2[10], [(0.0 / 0.0), 9.0, 8.0, 10.0]); - assertValueEquality(sortedTup2[11], [(), 4.0]); - int[][] arr2 = [[1, 9, 2], [0, 9, 1], [1, 7, 5], [9, 8, 2], [9, 8, 1]]; - [(int[])...] tup2 = [[1, 9, 2], [0, 9, 1], [1, 7, 5], [9, 8, 2], [9, 8, 1]]; int[][] sortedArr3 = arr2.sort(); - int[][] sortedTup3 = tup2.sort(); assertValueEquality(sortedArr3[0], [0, 9, 1]); assertValueEquality(sortedArr3[1], [1, 7, 5]); assertValueEquality(sortedArr3[2], [1, 9, 2]); assertValueEquality(sortedArr3[3], [9, 8, 1]); assertValueEquality(sortedArr3[4], [9, 8, 2]); - - assertValueEquality(sortedTup3[0], [0, 9, 1]); - assertValueEquality(sortedTup3[1], [1, 7, 5]); - assertValueEquality(sortedTup3[2], [1, 9, 2]); - assertValueEquality(sortedTup3[3], [9, 8, 1]); - assertValueEquality(sortedTup3[4], [9, 8, 2]); } function testSort8() { [int...][] arr = [[10, 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0]]; - [([int...])...] tup = [[10, 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0]]; [int...][] sortedArr = arr.sort(array:ASCENDING, isolated function([int...] x) returns int[] { return x; }); - [int...][] sortedTup = tup.sort(array:ASCENDING, isolated function([int...] x) returns int[] { - return x; - }); - assertValueEquality(sortedArr[0], [0, 9, 5]); assertValueEquality(sortedArr[1], [1, 1, 0]); assertValueEquality(sortedArr[2], [1, 2, 0]); @@ -1634,24 +1424,12 @@ function testSort8() { assertValueEquality(sortedArr[4], [1, 2, 5]); assertValueEquality(sortedArr[5], [10, 2, 0]); - assertValueEquality(sortedTup[0], [0, 9, 5]); - assertValueEquality(sortedTup[1], [1, 1, 0]); - assertValueEquality(sortedTup[2], [1, 2, 0]); - assertValueEquality(sortedTup[3], [1, 2, 0, 7]); - assertValueEquality(sortedTup[4], [1, 2, 5]); - assertValueEquality(sortedTup[5], [10, 2, 0]); - [int?...][] arr2 = [[(), 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0], [0, (), 9]]; - [([int?...])...] tup2 = [[(), 2, 0], [1, 2, 0, 7], [1, 2, 5], [0, 9, 5], [1, 2, 0], [1, 1, 0], [0, (), 9]]; [int?...][] sortedArr2 = arr2.sort(array:DESCENDING, isolated function(int?[] x) returns int?[] { return x; }); - [int?...][] sortedTup2 = tup2.sort(array:DESCENDING, isolated function(int?[] x) returns int?[] { - return x; - }); - assertValueEquality(sortedArr2[0], [1, 2, 5]); assertValueEquality(sortedArr2[1], [1, 2, 0, 7]); assertValueEquality(sortedArr2[2], [1, 2, 0]); @@ -1660,56 +1438,32 @@ function testSort8() { assertValueEquality(sortedArr2[5], [0, (), 9]); assertValueEquality(sortedArr2[6], [(), 2, 0]); - assertValueEquality(sortedTup2[0], [1, 2, 5]); - assertValueEquality(sortedTup2[1], [1, 2, 0, 7]); - assertValueEquality(sortedTup2[2], [1, 2, 0]); - assertValueEquality(sortedTup2[3], [1, 1, 0]); - assertValueEquality(sortedTup2[4], [0, 9, 5]); - assertValueEquality(sortedTup2[5], [0, (), 9]); - assertValueEquality(sortedTup2[6], [(), 2, 0]); - [int, boolean...][] arr3 = [[3, true, true, true], [5, true, false, true], [1, false, false]]; - [([int, boolean...])...] tup3 = [[3, true, true, true], [5, true, false, true], [1, false, false]]; [int, boolean...][] sortedArr3 = arr3.sort(array:ASCENDING, isolated function([int, boolean...] x) returns boolean[] { return [x[1], x[2]]; }); - [int, boolean...][] sortedTup3 = tup3.sort(array:ASCENDING, isolated function([int, boolean...] x) returns boolean[] { - return [x[1], x[2]]; - }); - assertValueEquality(sortedArr3[0], [1, false, false]); assertValueEquality(sortedArr3[1], [5, true, false, true]); assertValueEquality(sortedArr3[2], [3, true, true, true]); - - assertValueEquality(sortedTup3[0], [1, false, false]); - assertValueEquality(sortedTup3[1], [5, true, false, true]); - assertValueEquality(sortedTup3[2], [3, true, true, true]); } function testSort9() { strings:Char[] arr = ["s", "a", "b", "M", "Z"]; - [strings:Char...] tup = ["s", "a", "b", "M", "Z"]; strings:Char[] sortedArr = arr.sort(array:DESCENDING); - strings:Char[] sortedTup = tup.sort(array:DESCENDING); - assertValueEquality(sortedArr, ["s","b","a","Z","M"]); - assertValueEquality(sortedTup, ["s","b","a","Z","M"]); + assertValueEquality(sortedArr.toString(), "[\"s\",\"b\",\"a\",\"Z\",\"M\"]"); int[] arr2 = [4294967295, 4194967295, 4294967290, 4284967295, 3294967295, 1294967295]; - [int...] tup2 = [4294967295, 4194967295, 4294967290, 4284967295, 3294967295, 1294967295]; int[] sortedArr2 = arr2.sort(); - int[] sortedTup2 = tup2.sort(); - assertValueEquality(sortedArr2, [1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]); - assertValueEquality(sortedTup2, [1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]); + assertValueEquality(sortedArr2.toString(), + "[1294967295,3294967295,4194967295,4284967295,4294967290,4294967295]"); ints:Signed32[] arr3 = [2147483647, -2147483648, 2147483637, -1147483648, -2137483648, 1147483647]; - [ints:Signed32...] tup3 = [2147483647, -2147483648, 2147483637, -1147483648, -2137483648, 1147483647]; ints:Signed32[] sortedArr3 = arr3.sort(); - ints:Signed32[] sortedTup3 = tup3.sort(); assertValueEquality(sortedArr3[0], -2147483648); assertValueEquality(sortedArr3[1], -2137483648); @@ -1718,18 +1472,9 @@ function testSort9() { assertValueEquality(sortedArr3[4], 2147483637); assertValueEquality(sortedArr3[5], 2147483647); - assertValueEquality(sortedTup3[0], -2147483648); - assertValueEquality(sortedTup3[1], -2137483648); - assertValueEquality(sortedTup3[2], -1147483648); - assertValueEquality(sortedTup3[3], 1147483647); - assertValueEquality(sortedTup3[4], 2147483637); - assertValueEquality(sortedTup3[5], 2147483647); - ints:Signed16[] arr4 = [32765, -32768, 32767, -32668, -30768, 32567]; - [ints:Signed16...] tup4 = [32765, -32768, 32767, -32668, -30768, 32567]; ints:Signed16[] sortedArr4 = arr4.sort(array:DESCENDING); - ints:Signed16[] sortedTup4 = tup4.sort(array:DESCENDING); assertValueEquality(sortedArr4[0], 32767); assertValueEquality(sortedArr4[1], 32765); @@ -1738,18 +1483,9 @@ function testSort9() { assertValueEquality(sortedArr4[4], -32668); assertValueEquality(sortedArr4[5], -32768); - assertValueEquality(sortedTup4[0], 32767); - assertValueEquality(sortedTup4[1], 32765); - assertValueEquality(sortedTup4[2], 32567); - assertValueEquality(sortedTup4[3], -30768); - assertValueEquality(sortedTup4[4], -32668); - assertValueEquality(sortedTup4[5], -32768); - ints:Signed8[] arr5 = [-100, -123, 100, 67, -34, 52]; - [ints:Signed8...] tup5 = [-100, -123, 100, 67, -34, 52]; ints:Signed8[] sortedArr5 = arr5.sort(); - ints:Signed8[] sortedTup5 = tup5.sort(); assertValueEquality(sortedArr5[0], -123); assertValueEquality(sortedArr5[1], -100); @@ -1758,24 +1494,12 @@ function testSort9() { assertValueEquality(sortedArr5[4], 67); assertValueEquality(sortedArr5[5], 100); - assertValueEquality(sortedTup5[0], -123); - assertValueEquality(sortedTup5[1], -100); - assertValueEquality(sortedTup5[2], -34); - assertValueEquality(sortedTup5[3], 52); - assertValueEquality(sortedTup5[4], 67); - assertValueEquality(sortedTup5[5], 100); - ints:Unsigned32[] arr6 = [50, 4294967295, 0, 4294957295, 4294967294, 123, 214967295]; - [ints:Unsigned32...] tup6 = [50, 4294967295, 0, 4294957295, 4294967294, 123, 214967295]; ints:Unsigned32[] sortedArr6 = arr6.sort(array:ASCENDING, isolated function(ints:Unsigned32 x) returns ints:Unsigned32 { return x; }); - ints:Unsigned32[] sortedTup6 = tup6.sort(array:ASCENDING, isolated function(ints:Unsigned32 x) returns ints:Unsigned32 { - return x; - }); - assertValueEquality(sortedArr6[0], 0); assertValueEquality(sortedArr6[1], 50); assertValueEquality(sortedArr6[2], 123); @@ -1784,19 +1508,9 @@ function testSort9() { assertValueEquality(sortedArr6[5], 4294967294); assertValueEquality(sortedArr6[6], 4294967295); - assertValueEquality(sortedTup6[0], 0); - assertValueEquality(sortedTup6[1], 50); - assertValueEquality(sortedTup6[2], 123); - assertValueEquality(sortedTup6[3], 214967295); - assertValueEquality(sortedTup6[4], 4294957295); - assertValueEquality(sortedTup6[5], 4294967294); - assertValueEquality(sortedTup6[6], 4294967295); - ints:Unsigned16[] arr7 = [450, 65335, 0, 12, 65535, 12500, 4]; - [ints:Unsigned16...] tup7 = [450, 65335, 0, 12, 65535, 12500, 4]; ints:Unsigned16[] sortedArr7 = arr7.sort(array:DESCENDING); - ints:Unsigned16[] sortedTup7 = tup7.sort(array:DESCENDING); assertValueEquality(sortedArr7[0], 65535); assertValueEquality(sortedArr7[1], 65335); @@ -1806,19 +1520,9 @@ function testSort9() { assertValueEquality(sortedArr7[5], 4); assertValueEquality(sortedArr7[6], 0); - assertValueEquality(sortedTup7[0], 65535); - assertValueEquality(sortedTup7[1], 65335); - assertValueEquality(sortedTup7[2], 12500); - assertValueEquality(sortedTup7[3], 450); - assertValueEquality(sortedTup7[4], 12); - assertValueEquality(sortedTup7[5], 4); - assertValueEquality(sortedTup7[6], 0); - ints:Unsigned8[] arr8 = [221, 100, 0, 255, 24, 9, 2]; - [ints:Unsigned8...] tup8 = [221, 100, 0, 255, 24, 9, 2]; ints:Unsigned8[] sortedArr8 = arr8.sort(); - ints:Unsigned8[] sortedTup8 = tup8.sort(); assertValueEquality(sortedArr8[0], 0); assertValueEquality(sortedArr8[1], 2); @@ -1827,25 +1531,14 @@ function testSort9() { assertValueEquality(sortedArr8[4], 100); assertValueEquality(sortedArr8[5], 221); assertValueEquality(sortedArr8[6], 255); - - assertValueEquality(sortedTup8[0], 0); - assertValueEquality(sortedTup8[1], 2); - assertValueEquality(sortedTup8[2], 9); - assertValueEquality(sortedTup8[3], 24); - assertValueEquality(sortedTup8[4], 100); - assertValueEquality(sortedTup8[5], 221); - assertValueEquality(sortedTup8[6], 255); } function testSort10() { int[] arr = [10, 1, 3, 2, 0, 6]; - [int...] tup = [10, 1, 3, 2, 0, 6]; int[] sortedArr = arr.sort(array:ASCENDING, (i) => i); - int[] sortedTup = tup.sort(array:ASCENDING, (i) => i); - assertValueEquality(sortedArr, [0,1,2,3,6,10]); - assertValueEquality(sortedTup, [0,1,2,3,6,10]); + assertValueEquality(sortedArr.toString(), "[0,1,2,3,6,10]"); final int methodInt1 = 2; var addFunc1 = isolated function(int funcInt1) returns (int) { @@ -1859,96 +1552,27 @@ function testSort10() { }; int[] sortedArr2 = arr.sort(array:DESCENDING, addFunc1); - int[] sortedTup2 = tup.sort(array:DESCENDING, addFunc1); - assertValueEquality(sortedArr2, [10,6,3,2,1,0]); - assertValueEquality(sortedTup2, [10,6,3,2,1,0]); + assertValueEquality(sortedArr2.toString(), "[10,6,3,2,1,0]"); int[] sortedArr3 = array:sort(arr, array:ASCENDING, isolated function(int x) returns string[] => [x.toString(), "World"]); - int[] sortedTup3 = array:sort(tup, array:ASCENDING, isolated function(int x) returns string[] => [x.toString(), "World"]); - assertValueEquality(sortedArr3, [0,1,10,2,3,6]); - assertValueEquality(sortedTup3, [0,1,10,2,3,6]); + assertValueEquality(sortedArr3.toString(), "[0,1,10,2,3,6]"); int[] sortedArr4 = arr.sort(array:DESCENDING, (i) => i.toString()); - int[] sortedTup4 = tup.sort(array:DESCENDING, (i) => i.toString()); assertValueEquality(sortedArr4, [6, 3, 2, 10, 1, 0]); - assertValueEquality(sortedTup4, [6, 3, 2, 10, 1, 0]); int?[] arr2 = [(), 1, 3, 10, 0, 6]; - [int?...] tup2 = [(), 1, 3, 10, 0, 6]; int?[] sortedArr5 = arr2.sort(array:DESCENDING, (i) => i); - int?[] sortedTup5 = tup2.sort(array:DESCENDING, (i) => i); assertValueEquality(sortedArr5, [10, 6, 3, 1, 0, ()]); - assertValueEquality(sortedTup5, [10, 6, 3, 1, 0, ()]); int[] arr3 = []; - [int...] tup3 = []; int[] sortedArr6 = arr3.sort(array:DESCENDING, (i) => i); - int[] sortedTup6 = tup3.sort(array:DESCENDING, (i) => i); assertValueEquality(sortedArr6, []); - assertValueEquality(sortedTup6, []); -} - -type Grade2 1|15|"B"; -type Grade3 15|17|Grade3[]; -type Grade4 (Grade2|int)|Grade3; - -function testSort11() { - var keyFunc = isolated function((int|float|string|boolean) x) returns int { - if x is int { - return x; - } else if x is float { - return x; - }else if x is boolean{ - return 0; - }else { - return 100; - } - }; - - [int, float, string] tup1 = [7, 2.4, "Hello"]; - [int|float, float] tup2 = [89, 9.7]; - [boolean, string...] tup3 = [false, "Hello", "World"]; - [Grade2, Grade2, string, int...] tup4 = [1, 15, "Hello", 76, 89]; - - (int|float|string)[] sortedTup1 = tup1.sort("ascending", keyFunc); - (int|float)[] sortedTup2 = tup2.sort("descending", keyFunc); - (boolean|string)[] sortedTup3 = tup3.sort("descending", keyFunc); - (int|string)[] sortedTup4 = tup4.sort("descending", keyFunc); - - assertValueEquality(sortedTup1, [2.4, 7, "Hello"]); - assertValueEquality(sortedTup2, [89, 9.7]); - assertValueEquality(sortedTup3, ["Hello", "World", false]); - assertValueEquality(sortedTup4, ["Hello", 89, 76, 15, 1]); -} - -function testSortNegative() { - [int, float] tup1 = [5, 7.3]; - [int|float, float] tup2 = [5, 7.3]; - [Grade, Student] tup3 = ["A", {id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}]; - [15|17, 15|17|21, 15|17|"hello"] tup4 = [15, 21, 17]; - [int, Grade2] tup5 = [56, 1]; - [Student|int, int] tup6 = [{id: 1, fname: "Amber", fee: 10000.56, impact: 0.127, isUndergrad: true}, 7]; - [Grade3, int] tup7 = [17, 15]; - [Grade4, Grade3] tup8 = [1, 15]; - [(readonly & Person2 & Student2)|int, int] tup9 = [{id: 16158, name: "Arun", age: 12, average: 89.9, school: "JHC"}, 15]; - [((int|byte)|float), int] tup10 = [1, 15]; - [()|(), int] tup11 = [(),67]; - [json, json] tup12 = [{"abc":"defg"}, {"abc":"hello"}]; - anydata[][] items = [tup1, tup2, tup3, tup4, tup5, tup6, tup7, tup8, tup9, tup10, tup11, tup12]; - foreach anydata[] item in items { - any|error res = trap function:call(array:sort, item); - assertTrue(res is error); - if(res is error) { - assertValueEquality("{ballerina/lang.array}SortOperationError", res.message()); - assertValueEquality("valid key function required", checkpanic res.detail()["message"]); - } - } } function testTupleReverse() {