From da0b71e40481dfad6babd81078a7de8f87be9494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 18 Jan 2022 20:54:36 +0100 Subject: [PATCH] improve tests (#49) * improve tests Signed-off-by: Flipez * test missing emoji Signed-off-by: Flipez * remove expressionNode and statementNode Signed-off-by: Flipez * improve object/array tests Signed-off-by: Flipez * fix linter warnings Signed-off-by: Flipez * fix tests Signed-off-by: Flipez * add missing error checks * simplify make statements * increase test coverage even more Co-authored-by: Markus Freitag --- ast/array.go | 1 - ast/assign.go | 2 - ast/ast.go | 2 - ast/block.go | 1 - ast/boolean.go | 1 - ast/call.go | 1 - ast/expression_statement.go | 1 - ast/float.go | 1 - ast/foreach.go | 1 - ast/function.go | 1 - ast/hash.go | 1 - ast/identifier.go | 1 - ast/if.go | 1 - ast/import.go | 3 -- ast/index.go | 1 - ast/infix.go | 1 - ast/integer.go | 1 - ast/object_call.go | 1 - ast/prefix.go | 1 - ast/return.go | 1 - ast/string.go | 1 - evaluator/evaluator_test.go | 13 ++++++- object/array.go | 18 ++++----- object/array_test.go | 46 ++++++++++++++++++++++- object/boolean_test.go | 2 + object/builtin_test.go | 30 +++++++++++++++ object/file.go | 10 +++-- object/file_test.go | 4 +- object/hash.go | 2 +- object/hash_test.go | 12 ++++++ object/object.go | 10 ++--- object/object_test.go | 73 +++++++++++++++++++++++++++++++++++++ object/string.go | 4 +- object/string_test.go | 19 +++++++--- token/token_test.go | 16 ++++++++ utilities/utilities.go | 4 +- 36 files changed, 231 insertions(+), 57 deletions(-) create mode 100644 object/builtin_test.go create mode 100644 token/token_test.go diff --git a/ast/array.go b/ast/array.go index 1a3b3ea..7450eaf 100644 --- a/ast/array.go +++ b/ast/array.go @@ -12,7 +12,6 @@ type Array struct { Elements []Expression } -func (al *Array) expressionNode() {} func (al *Array) TokenLiteral() string { return al.Token.Literal } func (al *Array) String() string { var out bytes.Buffer diff --git a/ast/assign.go b/ast/assign.go index 4b78e26..08044cb 100644 --- a/ast/assign.go +++ b/ast/assign.go @@ -12,8 +12,6 @@ type Assign struct { Value Expression } -func (as *Assign) expressionNode() {} -func (as *Assign) statementNode() {} func (as *Assign) TokenLiteral() string { return as.Token.Literal } func (as *Assign) String() string { var out bytes.Buffer diff --git a/ast/ast.go b/ast/ast.go index 3f6153f..4ba6966 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -21,12 +21,10 @@ type Node interface { type Statement interface { Node - statementNode() } type Expression interface { Node - expressionNode() } type Program struct { diff --git a/ast/block.go b/ast/block.go index ac9799b..d2ea08d 100644 --- a/ast/block.go +++ b/ast/block.go @@ -11,7 +11,6 @@ type Block struct { Statements []Statement } -func (bs *Block) statementNode() {} func (bs *Block) TokenLiteral() string { return bs.Token.Literal } func (bs *Block) String() string { var out bytes.Buffer diff --git a/ast/boolean.go b/ast/boolean.go index 723b6d8..6c27c54 100644 --- a/ast/boolean.go +++ b/ast/boolean.go @@ -9,6 +9,5 @@ type Boolean struct { Value bool } -func (b *Boolean) expressionNode() {} func (b *Boolean) TokenLiteral() string { return b.Token.Literal } func (b *Boolean) String() string { return b.Token.Literal } diff --git a/ast/call.go b/ast/call.go index 9215842..e95c7f9 100644 --- a/ast/call.go +++ b/ast/call.go @@ -13,7 +13,6 @@ type Call struct { Arguments []Expression } -func (ce *Call) expressionNode() {} func (ce *Call) TokenLiteral() string { return ce.Token.Literal } func (ce *Call) String() string { var out bytes.Buffer diff --git a/ast/expression_statement.go b/ast/expression_statement.go index a033f59..9702405 100644 --- a/ast/expression_statement.go +++ b/ast/expression_statement.go @@ -9,7 +9,6 @@ type ExpressionStatement struct { Expression Expression } -func (es *ExpressionStatement) statementNode() {} func (es *ExpressionStatement) TokenLiteral() string { return es.Token.Literal } func (es *ExpressionStatement) String() string { if es.Expression != nil { diff --git a/ast/float.go b/ast/float.go index 037b5ea..d734e15 100644 --- a/ast/float.go +++ b/ast/float.go @@ -9,6 +9,5 @@ type Float struct { Value float64 } -func (fl *Float) expressionNode() {} func (fl *Float) TokenLiteral() string { return fl.Token.Literal } func (fl *Float) String() string { return fl.Token.Literal } diff --git a/ast/foreach.go b/ast/foreach.go index ae5925e..7d3470c 100644 --- a/ast/foreach.go +++ b/ast/foreach.go @@ -14,7 +14,6 @@ type Foreach struct { Body *Block } -func (fes *Foreach) expressionNode() {} func (fes *Foreach) TokenLiteral() string { return fes.Token.Literal } func (fes *Foreach) String() string { var out bytes.Buffer diff --git a/ast/function.go b/ast/function.go index ea6c1f6..d5853f6 100644 --- a/ast/function.go +++ b/ast/function.go @@ -14,7 +14,6 @@ type Function struct { Body *Block } -func (fl *Function) expressionNode() {} func (fl *Function) TokenLiteral() string { return fl.Token.Literal } func (fl *Function) String() string { var out bytes.Buffer diff --git a/ast/hash.go b/ast/hash.go index 8da4383..5188889 100644 --- a/ast/hash.go +++ b/ast/hash.go @@ -12,7 +12,6 @@ type Hash struct { Pairs map[Expression]Expression } -func (hl *Hash) expressionNode() {} func (hl *Hash) TokenLiteral() string { return hl.Token.Literal } func (hl *Hash) String() string { var out bytes.Buffer diff --git a/ast/identifier.go b/ast/identifier.go index 88a6e50..38f856d 100644 --- a/ast/identifier.go +++ b/ast/identifier.go @@ -9,6 +9,5 @@ type Identifier struct { Value string } -func (i *Identifier) expressionNode() {} func (i *Identifier) TokenLiteral() string { return i.Token.Literal } func (i *Identifier) String() string { return i.Value } diff --git a/ast/if.go b/ast/if.go index dcdba19..66064f3 100644 --- a/ast/if.go +++ b/ast/if.go @@ -13,7 +13,6 @@ type If struct { Alternative *Block } -func (ie *If) expressionNode() {} func (ie *If) TokenLiteral() string { return ie.Token.Literal } func (ie *If) String() string { var out bytes.Buffer diff --git a/ast/import.go b/ast/import.go index 2b5feb7..45096fa 100644 --- a/ast/import.go +++ b/ast/import.go @@ -12,10 +12,7 @@ type Import struct { Name Expression } -func (ie *Import) expressionNode() {} - func (ie *Import) TokenLiteral() string { return ie.Token.Literal } - func (ie *Import) String() string { var out bytes.Buffer diff --git a/ast/index.go b/ast/index.go index aaffe1c..96b03cb 100644 --- a/ast/index.go +++ b/ast/index.go @@ -12,7 +12,6 @@ type Index struct { Index Expression } -func (ie *Index) expressionNode() {} func (ie *Index) TokenLiteral() string { return ie.Token.Literal } func (ie *Index) String() string { var out bytes.Buffer diff --git a/ast/infix.go b/ast/infix.go index a1577b8..a8533ab 100644 --- a/ast/infix.go +++ b/ast/infix.go @@ -13,7 +13,6 @@ type Infix struct { Right Expression } -func (ie *Infix) expressionNode() {} func (ie *Infix) TokenLiteral() string { return ie.Token.Literal } func (ie *Infix) String() string { var out bytes.Buffer diff --git a/ast/integer.go b/ast/integer.go index 5c0553a..a6ae853 100644 --- a/ast/integer.go +++ b/ast/integer.go @@ -9,6 +9,5 @@ type Integer struct { Value int64 } -func (il *Integer) expressionNode() {} func (il *Integer) TokenLiteral() string { return il.Token.Literal } func (il *Integer) String() string { return il.Token.Literal } diff --git a/ast/object_call.go b/ast/object_call.go index baea2f6..7d93dc3 100644 --- a/ast/object_call.go +++ b/ast/object_call.go @@ -12,7 +12,6 @@ type ObjectCall struct { Call Expression } -func (oce *ObjectCall) expressionNode() {} func (oce *ObjectCall) TokenLiteral() string { return oce.Token.Literal } func (oce *ObjectCall) String() string { var out bytes.Buffer diff --git a/ast/prefix.go b/ast/prefix.go index 1299dd9..bde4471 100644 --- a/ast/prefix.go +++ b/ast/prefix.go @@ -12,7 +12,6 @@ type Prefix struct { Right Expression } -func (pe *Prefix) expressionNode() {} func (pe *Prefix) TokenLiteral() string { return pe.Token.Literal } func (pe *Prefix) String() string { var out bytes.Buffer diff --git a/ast/return.go b/ast/return.go index 52f88bf..55c307c 100644 --- a/ast/return.go +++ b/ast/return.go @@ -11,7 +11,6 @@ type Return struct { ReturnValue Expression } -func (rs *Return) statementNode() {} func (rs *Return) TokenLiteral() string { return rs.Token.Literal } func (rs *Return) String() string { var out bytes.Buffer diff --git a/ast/string.go b/ast/string.go index d2d5759..a149227 100644 --- a/ast/string.go +++ b/ast/string.go @@ -9,6 +9,5 @@ type String struct { Value string } -func (sl *String) expressionNode() {} func (sl *String) TokenLiteral() string { return sl.Token.Literal } func (sl *String) String() string { return sl.Token.Literal } diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index af9d58f..7cf88ce 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -29,6 +29,7 @@ func TestEvalIntegerExpression(t *testing.T) { {"3 * 3 * 3 + 10", 37}, {"3 * (3 * 3) + 10", 37}, {"(5 + 10 * 2 + 15 / 3) * 2 + -10", 50}, + {"5 ➕ 5 ➕ 5 ➕ 5 - 10", 10}, } for _, tt := range tests { @@ -67,6 +68,12 @@ func TestEvalBooleanExpression(t *testing.T) { {"(1 < 2) == false", false}, {"(1 > 2) == true", false}, {"(1 > 2) == false", true}, + {"👍", true}, + {"👎", false}, + {"👍 == 👍", true}, + {"👍 == 👎", false}, + {"👍 != 👎", true}, + {"👍 != 👍", false}, } for _, tt := range tests { @@ -173,6 +180,7 @@ func TestErrorHandling(t *testing.T) { }, {`"Hello" - "World"`, "unknown operator: STRING - STRING"}, {`{"name": "Monkey"}[def(x) { x }];`, "unusable as hash key: FUNCTION"}, + {"🔥 != 👍", "identifier not found: IDENT"}, } for _, tt := range tests { @@ -535,7 +543,10 @@ func TestImportExpression(t *testing.T) { } func TestImportSearchPaths(t *testing.T) { - utilities.AddPath("../stubs") + if err := utilities.AddPath("../stubs"); err != nil { + t.Errorf("error adding the stubs path: %s", err) + return + } tests := []struct { input string diff --git a/object/array.go b/object/array.go index de8d77f..c85d71e 100644 --- a/object/array.go +++ b/object/array.go @@ -16,10 +16,8 @@ func NewArray(slice []Object) *Array { } func NewArrayWithObjects(objs ...Object) *Array { - slice := make([]Object, len(objs), len(objs)) - for idx, obj := range objs { - slice[idx] = obj - } + slice := make([]Object, len(objs)) + copy(slice, objs) return NewArray(slice) } @@ -28,7 +26,7 @@ func (ao *Array) Inspect() string { var out bytes.Buffer length := len(ao.Elements) - elements := make([]string, length, length) + elements := make([]string, length) for index, element := range ao.Elements { elements[index] = element.Inspect() } @@ -81,7 +79,7 @@ func init() { } length := len(items) - newElements := make([]Object, length, length) + newElements := make([]Object, length) var idx int for _, item := range items { newElements[idx] = item @@ -125,7 +123,7 @@ func init() { method: func(o Object, _ []Object) Object { ao := o.(*Array) if len(ao.Elements) == 0 { - return new(Null) + return NULL } return ao.Elements[0] }, @@ -140,7 +138,7 @@ func init() { method: func(o Object, _ []Object) Object { ao := o.(*Array) if len(ao.Elements) == 0 { - return new(Null) + return NULL } return ao.Elements[len(ao.Elements)-1] }, @@ -160,7 +158,7 @@ func init() { ao := o.(*Array) length := len(ao.Elements) - newElements := make([]Object, length-1, length-1) + newElements := make([]Object, length-1) copy(newElements, ao.Elements[:(length-1)]) returnElement := ao.Elements[length-1] @@ -188,7 +186,7 @@ func init() { ao := o.(*Array) length := len(ao.Elements) - newElements := make([]Object, length+1, length+1) + newElements := make([]Object, length+1) copy(newElements, ao.Elements) newElements[length] = args[0] diff --git a/object/array_test.go b/object/array_test.go index b20534b..dd668bd 100644 --- a/object/array_test.go +++ b/object/array_test.go @@ -6,6 +6,27 @@ import ( "github.com/flipez/rocket-lang/object" ) +func TestNewArrayWithObjects(t *testing.T) { + arr := object.NewArrayWithObjects(object.NewString("a")) + if v := arr.Type(); v != object.ARRAY_OBJ { + t.Errorf("array.Type() return wrong type: %s", v) + } + + if v := arr.Elements[0].Type(); v != object.STRING_OBJ { + t.Errorf("first array element should be a string object") + } +} + +func TestArrayObject(t *testing.T) { + tests := []inputTestCase{ + {"[1] == [1]", true}, + {"[1] == [true]", false}, + {"[1] == [true, 1]", false}, + } + + testInput(t, tests) +} + func TestArrayObjectMethods(t *testing.T) { tests := []inputTestCase{ {`[1,2,3][0]`, 1}, @@ -19,8 +40,16 @@ func TestArrayObjectMethods(t *testing.T) { {`[1,2,3].index(4)`, -1}, {`[1,2,3].index(3)`, 2}, {`[1,2,3].index(true)`, -1}, - {`[1,2,3].index()`, "To few arguments: want=1, got=0"}, + {`[1,2,3].index()`, "to few arguments: want=1, got=0"}, {`a = []; b = []; foreach i in a { b.yoink(a[i]) }; a.size()==b.size()`, true}, + {`[1,1,2].uniq().size()`, 2}, + {`[true,true,2].uniq().size()`, 2}, + {`["test","test",2].uniq().size()`, 2}, + {`["12".reverse!()].uniq()`, "failed because element NULL is not hashable"}, + {"[].first()", "NULL"}, + {"[1,2,3].first()", 1}, + {"[].last()", "NULL"}, + {"[1,2,3].last()", 3}, } testInput(t, tests) @@ -33,3 +62,18 @@ func TestArrayInspect(t *testing.T) { t.Errorf("array.Type() returns wrong type") } } + +func TestArrayHashKey(t *testing.T) { + arr1 := &object.Array{Elements: []object.Object{}} + arr2 := &object.Array{Elements: []object.Object{}} + diff1 := &object.Array{Elements: []object.Object{&object.String{Value: "Hello World"}}} + diff2 := &object.Array{Elements: []object.Object{&object.String{Value: "Hello Another World"}}} + + if arr1.HashKey() != arr2.HashKey() { + t.Errorf("arrays with same content have different hash keys") + } + + if diff1.HashKey() == diff2.HashKey() { + t.Errorf("arrays with different content have same hash keys") + } +} diff --git a/object/boolean_test.go b/object/boolean_test.go index a16e279..55aa7d7 100644 --- a/object/boolean_test.go +++ b/object/boolean_test.go @@ -34,6 +34,8 @@ func TestBooleanObjectMethods(t *testing.T) { // other {"(true.wat().lines().size() == true.methods().size() + 1).plz_s()", "true"}, + {"true == true", true}, + {"true == false", false}, } testInput(t, tests) diff --git a/object/builtin_test.go b/object/builtin_test.go new file mode 100644 index 0000000..5a49dbb --- /dev/null +++ b/object/builtin_test.go @@ -0,0 +1,30 @@ +package object_test + +import ( + "testing" + + "github.com/flipez/rocket-lang/object" +) + +func TestBuiltinObjectMethods(t *testing.T) { + tests := []inputTestCase{ + {`puts.nope()`, "Failed to invoke method: nope"}, + } + + testInput(t, tests) +} + +func TestBuiltinType(t *testing.T) { + tests := []inputTestCase{ + {"puts", "builtin function"}, + } + + for _, tt := range tests { + def := testEval(tt.input).(*object.Builtin) + defInspect := def.Inspect() + + if defInspect != tt.expected { + t.Errorf("wrong string. expected=%#v, got=%#v", tt.expected, defInspect) + } + } +} diff --git a/object/file.go b/object/file.go index bffce5c..798ba9f 100644 --- a/object/file.go +++ b/object/file.go @@ -95,7 +95,7 @@ func init() { fileString := file.(*String) lines := strings.Split(fileString.Value, "\n") - result := make([]Object, len(lines), len(lines)) + result := make([]Object, len(lines)) for i, line := range lines { result[i] = NewString(line) @@ -210,17 +210,21 @@ func (f *File) InvokeMethod(method string, env Environment, args ...Object) Obje func readFile(o Object, _ []Object) Object { f := o.(*File) - f.Handle.Seek(0, 0) if f.Handle == nil { return NewError("Invalid file handle.") } + if _, err := f.Handle.Seek(0, 0); err != nil { + return NewError(err) + } file, err := ioutil.ReadAll(f.Handle) if err != nil { return NewError(err) } - f.Handle.Seek(0, 0) + if _, err := f.Handle.Seek(0, 0); err != nil { + return NewError(err) + } f.Position = 0 return NewString(string(file)) } diff --git a/object/file_test.go b/object/file_test.go index 83e862c..3202e59 100644 --- a/object/file_test.go +++ b/object/file_test.go @@ -10,8 +10,8 @@ func TestFileObjectMethods(t *testing.T) { {`open("../fixtures/module.rl").close()`, true}, {`a = open("../fixtures/module.rl"); a.close(); a.position()`, -1}, {`open("../fixtures/module.rl").content().size()`, 51}, - {`open("../fixtures/module.rl").content(1)`, "To many arguments: want=0, got=1"}, - {`open("../fixtures/module.rl").read()`, "To few arguments: want=1, got=0"}, + {`open("../fixtures/module.rl").content(1)`, "to many arguments: want=0, got=1"}, + {`open("../fixtures/module.rl").read()`, "to few arguments: want=1, got=0"}, {`open("../fixtures/module.rl").read(1)`, "a"}, {`open("../fixtures/module.rl").position()`, 0}, {`a = open("../fixtures/module.rl"); a.read(1); a.content(); a.position()`, 0}, diff --git a/object/hash.go b/object/hash.go index 78e2570..7c15a81 100644 --- a/object/hash.go +++ b/object/hash.go @@ -34,7 +34,7 @@ func (h *Hash) Inspect() string { var out bytes.Buffer length := len(h.Pairs) - pairs := make([]string, length, length) + pairs := make([]string, length) var index int for _, pair := range h.Pairs { pairs[index] = fmt.Sprintf("%s: %s", pair.Key.Inspect(), pair.Value.Inspect()) diff --git a/object/hash_test.go b/object/hash_test.go index c754d02..5d0a9dc 100644 --- a/object/hash_test.go +++ b/object/hash_test.go @@ -6,6 +6,18 @@ import ( "github.com/flipez/rocket-lang/object" ) +func TestHashObject(t *testing.T) { + tests := []inputTestCase{ + {`{"a": 1} == {"a": 1}`, true}, + {`{"a": 1} == {"a": 1, "b": 2}`, false}, + {`{"a": 1} == {"b": 1}`, false}, + {`{"a": 1} == {"a": "c"}`, false}, + {`{{1: true}: "a"}.keys()`, `[{1: true}]`}, + } + + testInput(t, tests) +} + func TestHashObjectMethods(t *testing.T) { tests := []inputTestCase{ {`{"a": 2}.keys()`, `["a"]`}, diff --git a/object/object.go b/object/object.go index f67cc40..b95476e 100644 --- a/object/object.go +++ b/object/object.go @@ -50,11 +50,11 @@ type ObjectMethod struct { func (om ObjectMethod) validateArgs(args []Object) error { if (len(args) < len(om.argPattern)) && !om.argsOptional { - return fmt.Errorf("To few arguments: want=%d, got=%d", len(om.argPattern), len(args)) + return fmt.Errorf("to few arguments: want=%d, got=%d", len(om.argPattern), len(args)) } if len(args) > len(om.argPattern) && !om.argOverloading { - return fmt.Errorf("To many arguments: want=%d, got=%d", len(om.argPattern), len(args)) + return fmt.Errorf("to many arguments: want=%d, got=%d", len(om.argPattern), len(args)) } if !om.argsOptional || (om.argsOptional && len(args) > 0) { @@ -67,7 +67,7 @@ func (om ObjectMethod) validateArgs(args []Object) error { } } if !valid { - return fmt.Errorf("Wrong argument type on position %d: got=%s, want=%s", idx, args[idx].Type(), strings.Join(pattern, "|")) + return fmt.Errorf("wrong argument type on position %d: got=%s, want=%s", idx, args[idx].Type(), strings.Join(pattern, "|")) } } } @@ -151,7 +151,7 @@ func init() { }, method: func(o Object, _ []Object) Object { oms := objectMethods[o.Type()] - result := make([]Object, len(oms), len(oms)) + result := make([]Object, len(oms)) var i int for name := range oms { result[i] = NewString(name) @@ -170,7 +170,7 @@ func init() { }, method: func(o Object, _ []Object) Object { oms := objectMethods[o.Type()] - result := make([]string, len(oms), len(oms)) + result := make([]string, len(oms)) var i int for name, objectMethod := range oms { result[i] = fmt.Sprintf("\t%s", objectMethod.Usage(name)) diff --git a/object/object_test.go b/object/object_test.go index 4cdf683..1fec74d 100644 --- a/object/object_test.go +++ b/object/object_test.go @@ -1,6 +1,8 @@ package object_test import ( + "errors" + "github.com/flipez/rocket-lang/evaluator" "github.com/flipez/rocket-lang/lexer" "github.com/flipez/rocket-lang/object" @@ -44,6 +46,10 @@ func testInput(t *testing.T, tests []inputTestCase) { testStringObject(t, strObj, expected) continue } + _, ok = evaluated.(*object.Null) + if ok { + continue + } errObj, ok := evaluated.(*object.Error) if !ok { @@ -58,3 +64,70 @@ func testInput(t *testing.T, tests []inputTestCase) { } } } + +func TestIsError(t *testing.T) { + trueErrors := []object.Object{ + object.NewError(errors.New("test error")), + object.NewError("test error"), + object.NewErrorFormat("test %s", "error"), + } + + for _, err := range trueErrors { + if !object.IsError(err) { + t.Errorf("'%s' should be an error", err.Inspect()) + } + } + + falseErrors := []object.Object{ + nil, + object.NewString("a"), + object.NULL, + } + for _, err := range falseErrors { + if object.IsError(nil) { + t.Errorf("'%#v' is not an error", err) + } + } +} + +func TestIsNumber(t *testing.T) { + if !object.IsNumber(object.NewInteger(1)) { + t.Error("INTEGER_OBJ should be a number") + } + if !object.IsNumber(object.NewFloat(1.1)) { + t.Error("FLOAT_OBJ should be a number") + } + if object.IsNumber(object.NULL) { + t.Error("NULL_OBJ is not a number") + } +} + +func TestIsTruthy(t *testing.T) { + if !object.IsTruthy(object.TRUE) { + t.Error("BOOLEAN_OBJ=true should be truthy") + } + if !object.IsTruthy(object.NewString("")) { + t.Error("STRING_OBJ should be truthy") + } + if object.IsTruthy(object.NULL) { + t.Error("NULL_OBJ should not be truthy") + } + if object.IsTruthy(object.FALSE) { + t.Errorf("BOOLEAN_OBJ=false, should not be truthy") + } +} + +func TestIsFalsy(t *testing.T) { + if object.IsFalsy(object.TRUE) { + t.Error("BOOLEAN_OBJ=true should not be falsy") + } + if object.IsFalsy(object.NewString("")) { + t.Error("STRING_OBJ should not be falsy") + } + if !object.IsFalsy(object.NULL) { + t.Error("NULL_OBJ should be falsy") + } + if !object.IsFalsy(object.FALSE) { + t.Errorf("BOOLEAN_OBJ=false, should be falsy") + } +} diff --git a/object/string.go b/object/string.go index 6bf7d42..6389a3e 100644 --- a/object/string.go +++ b/object/string.go @@ -194,7 +194,7 @@ func init() { fields := strings.Split(s.Value, sep) l := len(fields) - result := make([]Object, l, l) + result := make([]Object, l) for i, txt := range fields { result[i] = NewString(txt) } @@ -215,7 +215,7 @@ func init() { fields := strings.Split(s.Value, sep) l := len(fields) - result := make([]Object, l, l) + result := make([]Object, l) for i, txt := range fields { result[i] = NewString(txt) } diff --git a/object/string_test.go b/object/string_test.go index 08b3b85..4f20ab4 100644 --- a/object/string_test.go +++ b/object/string_test.go @@ -20,12 +20,19 @@ func testStringObject(t *testing.T, obj object.Object, expected string) bool { return true } +func TestStringObject(t *testing.T) { + tests := []inputTestCase{ + {`"a" == "a"`, true}, + } + testInput(t, tests) +} + func TestStringObjectMethods(t *testing.T) { tests := []inputTestCase{ {`"test".count("e")`, 1}, - {`"test".count()`, "To few arguments: want=1, got=0"}, + {`"test".count()`, "to few arguments: want=1, got=0"}, {`"test".find("e")`, 1}, - {`"test".find()`, "To few arguments: want=1, got=0"}, + {`"test".find()`, "to few arguments: want=1, got=0"}, {`"test".size()`, 4}, {`"test".plz_i()`, 0}, {`"125".plz_i()`, 125}, @@ -37,13 +44,13 @@ func TestStringObjectMethods(t *testing.T) { {`"0x1022".plz_i(8)`, 530}, {`"1022".plz_i(8)`, 530}, {`"test".replace("e", "s")`, "tsst"}, - {`"test".replace()`, "To few arguments: want=2, got=0"}, - {`"test".replace("e")`, "To few arguments: want=2, got=1"}, + {`"test".replace()`, "to few arguments: want=2, got=0"}, + {`"test".replace("e")`, "to few arguments: want=2, got=1"}, {`"test".reverse()`, "tset"}, {`"test test1".split()`, `["test", "test1"]`}, {`"test test1".split(",")`, `["test test1"]`}, - {`"test test1".split(",", "x")`, `To many arguments: want=1, got=2`}, - {`"test".split(1)`, `Wrong argument type on position 0: got=INTEGER, want=STRING`}, + {`"test test1".split(",", "x")`, `to many arguments: want=1, got=2`}, + {`"test".split(1)`, `wrong argument type on position 0: got=INTEGER, want=STRING`}, {`"test ".strip()`, "test"}, {`" test ".strip()`, "test"}, {`"test".strip()`, "test"}, diff --git a/token/token_test.go b/token/token_test.go new file mode 100644 index 0000000..024d1bc --- /dev/null +++ b/token/token_test.go @@ -0,0 +1,16 @@ +package token + +import ( + "testing" +) + +func TestNewToken(t *testing.T) { + token := NewToken(RBRACE, "}") + if token != (Token{Type: RBRACE, Literal: "}"}) { + t.Fatalf("wrong token received, got type `%s` and literal `%s`", token.Type, token.Literal) + } + token = NewToken(RBRACE, true) + if token != (Token{Type: ILLEGAL, Literal: "true"}) { + t.Fatalf("wrong token received, got type `%s` and literal `%s`", token.Type, token.Literal) + } +} diff --git a/utilities/utilities.go b/utilities/utilities.go index 31df374..0e4406e 100644 --- a/utilities/utilities.go +++ b/utilities/utilities.go @@ -21,7 +21,9 @@ func init() { tokens := strings.Split(e, ":") for _, token := range tokens { - AddPath(token) + if err := AddPath(token); err != nil { + log.Fatalf("error adding token: %s", err) + } } } else { SearchPaths = append(SearchPaths, cwd)