diff --git a/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredBuilder.java b/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredBuilder.java index d0734141c1..55c3bcc802 100644 --- a/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredBuilder.java +++ b/std-bits/table/src/main/java/org/enso/table/data/column/builder/InferredBuilder.java @@ -6,6 +6,7 @@ import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.List; import org.enso.base.polyglot.NumericConverter; +import org.enso.base.polyglot.Polyglot_Utils; import org.enso.table.data.column.storage.Storage; import org.enso.table.data.column.storage.type.BigIntegerType; import org.enso.table.data.column.storage.type.BooleanType; @@ -61,6 +62,9 @@ public class InferredBuilder extends Builder { @Override public void append(Object o) { + // ToDo: This a workaround for an issue with polyglot layer. #5590 is related. + o = Polyglot_Utils.convertPolyglotValue(o); + if (currentBuilder == null) { if (o == null) { currentSize++; diff --git a/test/Table_Tests/src/In_Memory/Column_Format_Spec.enso b/test/Table_Tests/src/In_Memory/Column_Format_Spec.enso index a2f6667420..0cefc8d0b9 100644 --- a/test/Table_Tests/src/In_Memory/Column_Format_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Column_Format_Spec.enso @@ -298,7 +298,7 @@ add_specs suite_builder = suite_builder.group "Edge cases" group_builder-> group_builder.specify "empty table is ok" <| input = Column.from_vector "values" [Date.new 2020 12 21, Date.new 2023 4 25] . take 0 - expected = Column.from_vector "values" [] + expected = Column.from_vector "values" [""] . take 0 actual = input.format "yyyyMMdd" actual . should_equal expected diff --git a/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso b/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso index b63708c56f..243e50213a 100644 --- a/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso +++ b/test/Table_Tests/src/In_Memory/Split_Tokenize_Spec.enso @@ -351,7 +351,7 @@ add_specs suite_builder = group_builder.specify "empty table" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] . take 0 - expected = Table.from_rows ["foo", "bar", "baz"] [] + expected = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] . take 0 actual = t.parse_to_columns "bar" "\d+" actual.should_equal expected @@ -380,13 +380,13 @@ add_specs suite_builder = group_builder.specify "input with no matches, with regex groups" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] - expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [["x", Nothing, Nothing, "y"]] + expected = Table.from_rows ["foo", "bar 1", "bar 2", "baz"] [["x", Nothing, Nothing, "y"], ["", "", "", ""]] . take 1 actual = t.parse_to_columns "bar" "(\d)(\d)" actual.should_equal expected group_builder.specify "input with no matches, with named and unnamed regex groups" <| t = Table.from_rows ["foo", "bar", "baz"] [["x", "a", "y"]] - expected = Table.from_rows ["foo", "quux", "bar 1", "foo 1", "bar 2", "baz"] [["x", Nothing, Nothing, Nothing, Nothing, "y"]] + expected = Table.from_rows ["foo", "quux", "bar 1", "foo 1", "bar 2", "baz"] [["x", Nothing, Nothing, Nothing, Nothing, "y"], ["", "", "", "", "", ""]] . take 1 actual = t.parse_to_columns "bar" "(?)(\d)(?\d)(\d)" actual.should_equal expected diff --git a/test/Table_Tests/src/Main.enso b/test/Table_Tests/src/Main.enso index bc7777cc5a..5a4fdc3387 100644 --- a/test/Table_Tests/src/Main.enso +++ b/test/Table_Tests/src/Main.enso @@ -7,6 +7,7 @@ import project.Formatting import project.Helpers import project.In_Memory import project.IO +import project.Util_Spec main filter=Nothing = suite = Test.build suite_builder-> @@ -15,5 +16,6 @@ main filter=Nothing = Formatting.Main.add_specs suite_builder Database.Main.add_specs suite_builder Helpers.Main.add_specs suite_builder + Util_Spec.add_specs suite_builder suite.run_with_filter filter diff --git a/test/Table_Tests/src/Util.enso b/test/Table_Tests/src/Util.enso index 48f9ec1d66..d1c59a4423 100644 --- a/test/Table_Tests/src/Util.enso +++ b/test/Table_Tests/src/Util.enso @@ -11,29 +11,14 @@ polyglot java import org.enso.base_test_helpers.FileSystemHelper Table.should_equal : Any -> Integer -> Any Table.should_equal self expected frames_to_skip=0 = loc = Meta.get_source_location 1+frames_to_skip - case expected of - _ : Table -> - tables_equal t0 t1 = - same_headers = (t0.columns.map .name) == (t1.columns.map .name) - same_columns = (t0.columns.map .to_vector) == (t1.columns.map .to_vector) - same_headers && same_columns - equal = tables_equal self expected - if equal.not then - msg = 'Tables differ at '+loc+'.\nActual:\n' + self.display + '\nExpected:\n' + expected.display - Test.fail msg - _ -> Test.fail "Got a Table, but expected a "+expected.to_display_text+' (at '+loc+').' + Panic.catch Test_Failure_Error (table_should_equal_impl self expected loc) error-> + Test.fail error.payload.message Column.should_equal : Any -> Integer -> Any Column.should_equal self expected frames_to_skip=0 = loc = Meta.get_source_location 1+frames_to_skip - case expected of - _ : Column -> - if self.name != expected.name then - Test.fail "Expected column name "+expected.name+", but got "+self.name+" (at "+loc+")." - if self.length != expected.length then - Test.fail "Expected column length "+expected.length.to_text+", but got "+self.length.to_text+" (at "+loc+")." - self.to_vector.should_equal expected.to_vector 2+frames_to_skip - _ -> Test.fail "Got a Column, but expected a "+expected.to_display_text+' (at '+loc+').' + Panic.catch Test_Failure_Error (column_should_equal_impl self expected loc) error-> + Test.fail error.payload.message DB_Table.should_equal : DB_Table -> Integer -> Any DB_Table.should_equal self expected frames_to_skip=0 = @@ -47,6 +32,60 @@ DB_Column.should_equal self expected frames_to_skip=0 = t1 = expected.read t0 . should_equal t1 frames_to_skip +type Test_Failure_Error + ## PRIVATE + The runtime representation of a test failure. + + Arguments: + - message: A description of the test failure. + Error message + + ## PRIVATE + to_display_text : Text + to_display_text self = "Test failure error: "+self.message + +## PRIVATE +table_should_equal_impl actual expected loc = + case expected of + _ : Table -> + if actual.columns.length != expected.columns.length then + Panic.throw (Test_Failure_Error.Error 'Tables differ at '+loc+'.\nActual:\n'+actual.display+'\nExpected:\n'+expected.display+'\nExpected '+expected.columns.length.to_text+" columns, but got "+actual.columns.length.to_text+'.') + Panic.catch Test_Failure_Error (actual.columns.zip expected.columns a-> e->(column_should_equal_impl a e)) error-> + msg = 'Tables differ at '+loc+'.\nActual:\n'+actual.display+'\nExpected:\n'+expected.display+'\n'+error.payload.message + Panic.throw (Test_Failure_Error.Error msg) + _ -> Panic.throw (Test_Failure_Error.Error "Got a Table, but expected a "+expected.to_display_text+(display_loc loc)+'.') + +## PRIVATE +column_should_equal_impl actual expected loc='' = + case expected of + _ : Column -> + if actual.name != expected.name then + Panic.throw (Test_Failure_Error.Error "Expected column name "+expected.name+", but got "+actual.name+(display_loc loc)+'.') + if actual.length != expected.length then + Panic.throw (Test_Failure_Error.Error "Expected column length "+expected.length.to_text+", but got "+actual.length.to_text+(display_loc loc)+'.') + if actual.value_type != expected.value_type then + Panic.throw (Test_Failure_Error.Error "Expected column type "+expected.value_type.to_text+", but got "+actual.value_type.to_text+(display_loc loc)+'.') + actual.zip expected a-> e-> + if values_equal a e then + report_fail actual expected loc + _ -> Panic.throw (Test_Failure_Error.Error "Got a Column, but expected a "+expected.to_display_text+(display_loc loc)+'.') + +## PRIVATE +values_equal a e = + a != e && (a.is_a Number && e.is_a Number && a.is_nan && e.is_nan).not + +## PRIVATE +report_fail actual expected loc = + indexed = actual.zip (0.up_to actual.length) a-> i-> Pair.new a i + indexed.zip expected a-> e-> + if values_equal a.first e then + Panic.throw (Test_Failure_Error.Error "Column: "+actual.name+" differs at row "+a.second.to_text+'.\n\t Actual : '+a.first.to_text+'\n\t Expected: '+e.to_text+'\n\t'+(display_loc loc)+'.') + +## PRIVATE +display_loc loc:Text = + if loc.is_empty then '' else + ' (at '+loc+')' + normalize_lines string line_separator=Line_Ending_Style.Unix.to_text newline_at_end=True = case newline_at_end of True -> string.lines.join line_separator suffix=line_separator diff --git a/test/Table_Tests/src/Util_Spec.enso b/test/Table_Tests/src/Util_Spec.enso new file mode 100644 index 0000000000..f8f02507d2 --- /dev/null +++ b/test/Table_Tests/src/Util_Spec.enso @@ -0,0 +1,81 @@ +from Standard.Base import all +from Standard.Table import Column, Table +from project.Util import all +from Standard.Test import all + +add_specs suite_builder = + suite_builder.group "Column should_equal" group_builder-> + group_builder.specify "Two Columns Are Equal" <| + expected_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"] + actual_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"] + actual_column.should_equal expected_column + group_builder.specify "Two Columns With Different Name are Not Equal" <| + expected_column = Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"] + actual_column = Column.from_vector "Col2" ["Quis", "custodiet", "ipsos", "custodes?"] + res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH") + res.catch.message.should_equal "Expected column name Col1, but got Col2 (at LOCATION_PATH)." + group_builder.specify "Two Columns With Different Lengths are Not Equal" <| + expected_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"] + actual_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos"] + res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH") + res.catch.message.should_equal "Expected column length 4, but got 3 (at LOCATION_PATH)." + group_builder.specify "Two Columns with different content Are Not Equal" <| + expected_column = Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"] + actual_column = Column.from_vector "Col" ["Who", "guards", "the", "guards?"] + res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH") + res.catch.message.should_equal 'Column: Col differs at row 0.\n\t Actual : Who\n\t Expected: Quis\n\t (at LOCATION_PATH).' + group_builder.specify "Two Columns Are Not Equal in Row 3" <| + expected_column = Column.from_vector "My Column" ["Quis", "custodiet", "ipsos", "custodes?"] + actual_column = Column.from_vector "My Column" ["Quis", "custodiet", "ipsos", "guards?"] + res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH") + res.catch.message.should_equal 'Column: My Column differs at row 3.\n\t Actual : guards?\n\t Expected: custodes?\n\t (at LOCATION_PATH).' + group_builder.specify "Two Columns with different types Are Not Equal" <| + expected_column = Column.from_vector "Col" ["1", "2", "3", "4"] + actual_column = Column.from_vector "Col" [1, 2, 3, 4] + res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH") + res.catch.message.should_equal "Expected column type (Char Nothing True), but got (Integer 64 bits) (at LOCATION_PATH)." + group_builder.specify "Comparing a Column to non column" <| + expected_column = 42 + actual_column = Column.from_vector "Col" [1, 2, 3, 4] + res = Panic.recover Test_Failure_Error (column_should_equal_impl actual_column expected_column "LOCATION_PATH") + res.catch.message.should_equal "Got a Column, but expected a 42 (at LOCATION_PATH)." + group_builder.specify "Two Columns Containg NaNs Are Equal" <| + # This is somewhat of a special case, as NaN != NaN but for the purposes of testing we consider them equal + expected_column = Column.from_vector "Col" [1.0, 2.0, Number.nan] + actual_column = Column.from_vector "Col" [1.0, 2.0, Number.nan] + actual_column.should_equal expected_column + suite_builder.group "Table should_equal" group_builder-> + group_builder.specify "Two Tables Are Equal" <| + expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]] + actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]] + actual_table.should_equal expected_table + group_builder.specify "Two Tables With Different Values" <| + expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]] + actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "teh", "guards?"]] + res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH") + res.catch.message.should_end_with 'Column: Col2 differs at row 2.\n\t Actual : teh\n\t Expected: the\n\t.' + group_builder.specify "Tables different number of columns" <| + expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"]] + actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]] + res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH") + res.catch.message.should_end_with "Expected 1 columns, but got 2." + group_builder.specify "Tables different number of columns2" <| + expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]] + actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"]] + res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH") + res.catch.message.should_end_with "Expected 2 columns, but got 1." + group_builder.specify "Tables With Mismatched Column names" <| + expected_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]] + actual_table = Table.new [Column.from_vector "Col" ["Quis", "custodiet", "ipsos", "custodes?"], Column.from_vector "Col2" ["Who", "guards", "the", "guards?"]] + res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH") + res.catch.message.should_end_with "Expected column name Col1, but got Col." + group_builder.specify "Comparing a Table to non Table" <| + expected_table = 42 + actual_table = Table.new [Column.from_vector "Col1" ["Quis", "custodiet", "ipsos", "custodes?"]] + res = Panic.recover Test_Failure_Error (table_should_equal_impl actual_table expected_table "LOCATION_PATH") + res.catch.message.should_equal "Got a Table, but expected a 42 (at LOCATION_PATH)." + +main filter=Nothing = + suite = Test.build suite_builder-> + add_specs suite_builder + suite.run_with_filter filter