From b9a952ae6ed51c6497a8dd3639e175e6f53eca9c Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Wed, 18 Oct 2023 11:10:42 +1100 Subject: [PATCH] Fixing tests --- pkg/yqlib/candidate_node_goccy_yaml.go | 3 +- pkg/yqlib/candidate_node_yaml.go | 29 -- pkg/yqlib/candidiate_node_json.go | 5 - pkg/yqlib/decoder_lua.go | 8 +- pkg/yqlib/doc/operators/equals.md | 110 +++++++ pkg/yqlib/json_test.go | 20 +- pkg/yqlib/lua_test.go | 32 ++ pkg/yqlib/operator_anchors_aliases_test.go | 18 +- pkg/yqlib/operator_equals_test.go | 350 ++++++++++----------- pkg/yqlib/operator_keys.go | 1 - pkg/yqlib/operators_test.go | 2 +- 11 files changed, 352 insertions(+), 226 deletions(-) diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go index c29f7419..7974c723 100644 --- a/pkg/yqlib/candidate_node_goccy_yaml.go +++ b/pkg/yqlib/candidate_node_goccy_yaml.go @@ -174,8 +174,7 @@ func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingVa if mappingEntry.FootComment != nil { valueNode.FootComment = mappingEntry.FootComment.String() } - - o.Content = append(o.Content, keyNode, valueNode) + o.AddKeyValueChild(keyNode, valueNode) return nil } diff --git a/pkg/yqlib/candidate_node_yaml.go b/pkg/yqlib/candidate_node_yaml.go index 2b4085f9..67f57a48 100644 --- a/pkg/yqlib/candidate_node_yaml.go +++ b/pkg/yqlib/candidate_node_yaml.go @@ -108,22 +108,6 @@ func (o *CandidateNode) decodeIntoChild(childNode *yaml.Node, anchorMap map[stri func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*CandidateNode) error { log.Debugf("UnmarshalYAML %v", node.Tag) switch node.Kind { - // case yaml.DocumentNode: - // log.Debugf("UnmarshalYAML - a document") - // o.Kind = DocumentNode - // o.copyFromYamlNode(node, anchorMap) - // if len(node.Content) == 0 { - // return nil - // } - - // singleChild, err := o.decodeIntoChild(node.Content[0], anchorMap) - - // if err != nil { - // return err - // } - // o.Content = []*CandidateNode{singleChild} - // log.Debugf("UnmarshalYAML - finished document node") - // return nil case yaml.AliasNode: log.Debug("UnmarshalYAML - alias from yaml: %v", o.Tag) o.Kind = AliasNode @@ -197,19 +181,6 @@ func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*Can func (o *CandidateNode) MarshalYAML() (*yaml.Node, error) { log.Debug("MarshalYAML to yaml: %v", o.Tag) switch o.Kind { - // case DocumentNode: - // log.Debug("MarshalYAML its a document") - // target := &yaml.Node{Kind: yaml.DocumentNode} - // o.copyToYamlNode(target) - - // singleChild, err := o.Content[0].MarshalYAML() - - // log.Debug("MarshalYAML its a document - singChild is %v", singleChild) - // if err != nil { - // return nil, err - // } - // target.Content = []*yaml.Node{singleChild} - // return target, nil case AliasNode: log.Debug("MarshalYAML - alias to yaml: %v", o.Tag) target := &yaml.Node{Kind: yaml.AliasNode} diff --git a/pkg/yqlib/candidiate_node_json.go b/pkg/yqlib/candidiate_node_json.go index 4971557d..728e5afb 100644 --- a/pkg/yqlib/candidiate_node_json.go +++ b/pkg/yqlib/candidiate_node_json.go @@ -76,7 +76,6 @@ func (o *CandidateNode) UnmarshalJSON(data []byte) error { if err := dec.Decode(childValue); err != nil { return err } - o.Content = append(o.Content, childKey, childValue) } // unexpected error @@ -133,10 +132,6 @@ func (o *CandidateNode) MarshalJSON() ([]byte, error) { enc.SetEscapeHTML(false) // do not escape html chars e.g. &, <, > switch o.Kind { - // case DocumentNode: - // log.Debugf("MarshalJSON DocumentNode") - // err := enc.Encode(o.Content[0]) - // return buf.Bytes(), err case AliasNode: log.Debugf("MarshalJSON AliasNode") err := enc.Encode(o.Alias) diff --git a/pkg/yqlib/decoder_lua.go b/pkg/yqlib/decoder_lua.go index acad40f9..b37be846 100644 --- a/pkg/yqlib/decoder_lua.go +++ b/pkg/yqlib/decoder_lua.go @@ -112,11 +112,13 @@ func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *Candida } else { i = 0 } - yaml_map.Content = append(yaml_map.Content, dec.convertToYamlNode(ls, k)) + newKey := dec.convertToYamlNode(ls, k) + yv := dec.convertToYamlNode(ls, v) - yaml_map.Content = append(yaml_map.Content, yv) + yaml_map.AddKeyValueChild(newKey, yv) + if i != 0 { - yaml_sequence.Content = append(yaml_sequence.Content, yv) + yaml_sequence.AddChild(yv) } k, v = ls.Next(t, k) } diff --git a/pkg/yqlib/doc/operators/equals.md b/pkg/yqlib/doc/operators/equals.md index 9f9fd0e2..ca5099b7 100644 --- a/pkg/yqlib/doc/operators/equals.md +++ b/pkg/yqlib/doc/operators/equals.md @@ -21,3 +21,113 @@ The not equals `!=` operator returns `false` if the LHS is equal to the RHS. - select operator [here](https://mikefarah.gitbook.io/yq/operators/select) +## Match string +Given a sample.yml file of: +```yaml +- cat +- goat +- dog +``` +then +```bash +yq '.[] | (. == "*at")' sample.yml +``` +will output +```yaml +true +true +false +``` + +## Don't match string +Given a sample.yml file of: +```yaml +- cat +- goat +- dog +``` +then +```bash +yq '.[] | (. != "*at")' sample.yml +``` +will output +```yaml +false +false +true +``` + +## Match number +Given a sample.yml file of: +```yaml +- 3 +- 4 +- 5 +``` +then +```bash +yq '.[] | (. == 4)' sample.yml +``` +will output +```yaml +false +true +false +``` + +## Don't match number +Given a sample.yml file of: +```yaml +- 3 +- 4 +- 5 +``` +then +```bash +yq '.[] | (. != 4)' sample.yml +``` +will output +```yaml +true +false +true +``` + +## Match nulls +Running +```bash +yq --null-input 'null == ~' +``` +will output +```yaml +true +``` + +## Non existent key doesn't equal a value +Given a sample.yml file of: +```yaml +a: frog +``` +then +```bash +yq 'select(.b != "thing")' sample.yml +``` +will output +```yaml +a: frog +``` + +## Two non existent keys are equal +Given a sample.yml file of: +```yaml +a: frog +``` +then +```bash +yq 'select(.b == .c)' sample.yml +``` +will output +```yaml +a: frog +``` + diff --git a/pkg/yqlib/json_test.go b/pkg/yqlib/json_test.go index 80c554dc..ab0c7225 100644 --- a/pkg/yqlib/json_test.go +++ b/pkg/yqlib/json_test.go @@ -126,6 +126,22 @@ var jsonScenarios = []formatScenario{ expected: "[\"cat\"]\n", scenarioType: "decode", }, + { + skipDoc: true, + description: "Parse json: deeper: path", + input: `{"cat": {"noises": "meow"}}`, + expression: ".cat.noises | path", + expected: "[\"cat\",\"noises\"]\n", + scenarioType: "decode", + }, + { + skipDoc: true, + description: "Parse json: array path", + input: `{"cat": {"noises": ["meow"]}}`, + expression: ".cat.noises[0] | path", + expected: "[\"cat\",\"noises\",0]\n", + scenarioType: "decode", + }, { description: "bad json", skipDoc: true, @@ -342,8 +358,10 @@ func decodeJSON(t *testing.T, jsonString string) *CandidateNode { func testJSONScenario(t *testing.T, s formatScenario) { switch s.scenarioType { - case "encode", "decode": + case "encode": test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewJSONEncoder(s.indent, false, false)), s.description) + case "decode": + test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewJSONDecoder(), NewJSONEncoder(s.indent, false, false)), s.description) case "decode-ndjson": test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewJSONDecoder(), NewYamlEncoder(2, false, ConfiguredYamlPreferences)), s.description) case "roundtrip-ndjson": diff --git a/pkg/yqlib/lua_test.go b/pkg/yqlib/lua_test.go index bb36e9cc..6e0bc8b6 100644 --- a/pkg/yqlib/lua_test.go +++ b/pkg/yqlib/lua_test.go @@ -31,6 +31,38 @@ cities: - Perth `, }, + { + skipDoc: true, + description: "path", + expression: ".cities[2] | path", + input: `return { + ["country"] = "Australia"; -- this place + ["cities"] = { + "Sydney", + "Melbourne", + "Brisbane", + "Perth", + }; +}; +`, + expected: "- cities\n- 2\n", + }, + { + skipDoc: true, + description: "path", + expression: ".cities[2] | key", + input: `return { + ["country"] = "Australia"; -- this place + ["cities"] = { + "Sydney", + "Melbourne", + "Brisbane", + "Perth", + }; +}; +`, + expected: "2\n", + }, { description: "Basic output example", scenarioType: "encode", diff --git a/pkg/yqlib/operator_anchors_aliases_test.go b/pkg/yqlib/operator_anchors_aliases_test.go index befd7be9..f866aca5 100644 --- a/pkg/yqlib/operator_anchors_aliases_test.go +++ b/pkg/yqlib/operator_anchors_aliases_test.go @@ -170,15 +170,15 @@ var anchorOperatorScenarios = []expressionScenario{ "D0, P[], (!!map)::{b: &meow purr, a: *meow}\n", }, }, - // { - // description: "Dont explode alias and anchor - check alias parent", - // skipDoc: true, - // document: `{a: &a [1], b: *a}`, - // expression: `.b[]`, - // expected: []string{ - // "D0, P[b], (!!str)::cat\n", - // }, - // }, + { + description: "Dont explode alias and anchor - check alias parent", + skipDoc: true, + document: `{a: &a [1], b: *a}`, + expression: `.b[]`, + expected: []string{ + "D0, P[a 0], (!!int)::1\n", + }, + }, { description: "Explode alias and anchor - check alias parent", skipDoc: true, diff --git a/pkg/yqlib/operator_equals_test.go b/pkg/yqlib/operator_equals_test.go index 258567c3..43a2fa86 100644 --- a/pkg/yqlib/operator_equals_test.go +++ b/pkg/yqlib/operator_equals_test.go @@ -12,181 +12,181 @@ var equalsOperatorScenarios = []expressionScenario{ "D0, P[a], (!!bool)::true\n", }, }, - // { - // expression: `(.k | length) == 0`, - // skipDoc: true, - // expected: []string{ - // "D0, P[k], (!!bool)::true\n", - // }, - // }, - // { - // skipDoc: true, - // document: `a: cat`, - // expression: ".a == .b", - // expected: []string{ - // "D0, P[a], (!!bool)::false\n", - // }, - // }, - // { - // skipDoc: true, - // document: `a: cat`, - // expression: ".b == .a", - // expected: []string{ - // "D0, P[b], (!!bool)::false\n", - // }, - // }, - // { - // skipDoc: true, - // document: "cat", - // document2: "dog", - // expression: "select(fi==0) == select(fi==1)", - // expected: []string{ - // "D0, P[], (!!bool)::false\n", - // }, - // }, - // { - // skipDoc: true, - // document: "{}", - // expression: "(.a == .b) as $x | .", - // expected: []string{ - // "D0, P[], (!!map)::{}\n", - // }, - // }, - // { - // skipDoc: true, - // document: "{}", - // expression: ".a == .b", - // expected: []string{ - // "D0, P[a], (!!bool)::true\n", - // }, - // }, - // { - // skipDoc: true, - // document: "{}", - // expression: "(.a != .b) as $x | .", - // expected: []string{ - // "D0, P[], (!!map)::{}\n", - // }, - // }, - // { - // skipDoc: true, - // document: "{}", - // expression: ".a != .b", - // expected: []string{ - // "D0, P[], (!!bool)::false\n", - // }, - // }, - // { - // skipDoc: true, - // document: "{a: {b: 10}}", - // expression: "select(.c != null)", - // expected: []string{}, - // }, - // { - // skipDoc: true, - // document: "{a: {b: 10}}", - // expression: "select(.d == .c)", - // expected: []string{ - // "D0, P[], (!!map)::{a: {b: 10}}\n", - // }, - // }, - // { - // skipDoc: true, - // document: "{a: {b: 10}}", - // expression: "select(null == .c)", - // expected: []string{ - // "D0, P[], (!!map)::{a: {b: 10}}\n", - // }, - // }, - // { - // skipDoc: true, - // document: "{a: { b: {things: \"\"}, f: [1], g: [] }}", - // expression: ".. | select(. == \"\")", - // expected: []string{ - // "D0, P[a b things], (!!str)::\n", - // }, - // }, - // { - // description: "Match string", - // document: `[cat,goat,dog]`, - // expression: `.[] | (. == "*at")`, - // expected: []string{ - // "D0, P[0], (!!bool)::true\n", - // "D0, P[1], (!!bool)::true\n", - // "D0, P[2], (!!bool)::false\n", - // }, - // }, - // { - // description: "Don't match string", - // document: `[cat,goat,dog]`, - // expression: `.[] | (. != "*at")`, - // expected: []string{ - // "D0, P[0], (!!bool)::false\n", - // "D0, P[1], (!!bool)::false\n", - // "D0, P[2], (!!bool)::true\n", - // }, - // }, - // { - // description: "Match number", - // document: `[3, 4, 5]`, - // expression: `.[] | (. == 4)`, - // expected: []string{ - // "D0, P[0], (!!bool)::false\n", - // "D0, P[1], (!!bool)::true\n", - // "D0, P[2], (!!bool)::false\n", - // }, - // }, - // { - // description: "Don't match number", - // document: `[3, 4, 5]`, - // expression: `.[] | (. != 4)`, - // expected: []string{ - // "D0, P[0], (!!bool)::true\n", - // "D0, P[1], (!!bool)::false\n", - // "D0, P[2], (!!bool)::true\n", - // }, - // }, - // { - // skipDoc: true, - // document: `a: { cat: {b: apple, c: whatever}, pat: {b: banana} }`, - // expression: `.a | (.[].b == "apple")`, - // expected: []string{ - // "D0, P[a cat b], (!!bool)::true\n", - // "D0, P[a pat b], (!!bool)::false\n", - // }, - // }, - // { - // skipDoc: true, - // document: ``, - // expression: `null == null`, - // expected: []string{ - // "D0, P[], (!!bool)::true\n", - // }, - // }, - // { - // description: "Match nulls", - // document: ``, - // expression: `null == ~`, - // expected: []string{ - // "D0, P[], (!!bool)::true\n", - // }, - // }, - // { - // description: "Non existent key doesn't equal a value", - // document: "a: frog", - // expression: `select(.b != "thing")`, - // expected: []string{ - // "D0, P[], (!!map)::a: frog\n", - // }, - // }, - // { - // description: "Two non existent keys are equal", - // document: "a: frog", - // expression: `select(.b == .c)`, - // expected: []string{ - // "D0, P[], (!!map)::a: frog\n", - // }, - // }, + { + expression: `(.k | length) == 0`, + skipDoc: true, + expected: []string{ + "D0, P[k], (!!bool)::true\n", + }, + }, + { + skipDoc: true, + document: `a: cat`, + expression: ".a == .b", + expected: []string{ + "D0, P[a], (!!bool)::false\n", + }, + }, + { + skipDoc: true, + document: `a: cat`, + expression: ".b == .a", + expected: []string{ + "D0, P[b], (!!bool)::false\n", + }, + }, + { + skipDoc: true, + document: "cat", + document2: "dog", + expression: "select(fi==0) == select(fi==1)", + expected: []string{ + "D0, P[], (!!bool)::false\n", + }, + }, + { + skipDoc: true, + document: "{}", + expression: "(.a == .b) as $x | .", + expected: []string{ + "D0, P[], (!!map)::{}\n", + }, + }, + { + skipDoc: true, + document: "{}", + expression: ".a == .b", + expected: []string{ + "D0, P[a], (!!bool)::true\n", + }, + }, + { + skipDoc: true, + document: "{}", + expression: "(.a != .b) as $x | .", + expected: []string{ + "D0, P[], (!!map)::{}\n", + }, + }, + { + skipDoc: true, + document: "{}", + expression: ".a != .b", + expected: []string{ + "D0, P[], (!!bool)::false\n", + }, + }, + { + skipDoc: true, + document: "{a: {b: 10}}", + expression: "select(.c != null)", + expected: []string{}, + }, + { + skipDoc: true, + document: "{a: {b: 10}}", + expression: "select(.d == .c)", + expected: []string{ + "D0, P[], (!!map)::{a: {b: 10}}\n", + }, + }, + { + skipDoc: true, + document: "{a: {b: 10}}", + expression: "select(null == .c)", + expected: []string{ + "D0, P[], (!!map)::{a: {b: 10}}\n", + }, + }, + { + skipDoc: true, + document: "{a: { b: {things: \"\"}, f: [1], g: [] }}", + expression: ".. | select(. == \"\")", + expected: []string{ + "D0, P[a b things], (!!str)::\n", + }, + }, + { + description: "Match string", + document: `[cat,goat,dog]`, + expression: `.[] | (. == "*at")`, + expected: []string{ + "D0, P[0], (!!bool)::true\n", + "D0, P[1], (!!bool)::true\n", + "D0, P[2], (!!bool)::false\n", + }, + }, + { + description: "Don't match string", + document: `[cat,goat,dog]`, + expression: `.[] | (. != "*at")`, + expected: []string{ + "D0, P[0], (!!bool)::false\n", + "D0, P[1], (!!bool)::false\n", + "D0, P[2], (!!bool)::true\n", + }, + }, + { + description: "Match number", + document: `[3, 4, 5]`, + expression: `.[] | (. == 4)`, + expected: []string{ + "D0, P[0], (!!bool)::false\n", + "D0, P[1], (!!bool)::true\n", + "D0, P[2], (!!bool)::false\n", + }, + }, + { + description: "Don't match number", + document: `[3, 4, 5]`, + expression: `.[] | (. != 4)`, + expected: []string{ + "D0, P[0], (!!bool)::true\n", + "D0, P[1], (!!bool)::false\n", + "D0, P[2], (!!bool)::true\n", + }, + }, + { + skipDoc: true, + document: `a: { cat: {b: apple, c: whatever}, pat: {b: banana} }`, + expression: `.a | (.[].b == "apple")`, + expected: []string{ + "D0, P[a cat b], (!!bool)::true\n", + "D0, P[a pat b], (!!bool)::false\n", + }, + }, + { + skipDoc: true, + document: ``, + expression: `null == null`, + expected: []string{ + "D0, P[], (!!bool)::true\n", + }, + }, + { + description: "Match nulls", + document: ``, + expression: `null == ~`, + expected: []string{ + "D0, P[], (!!bool)::true\n", + }, + }, + { + description: "Non existent key doesn't equal a value", + document: "a: frog", + expression: `select(.b != "thing")`, + expected: []string{ + "D0, P[], (!!map)::a: frog\n", + }, + }, + { + description: "Two non existent keys are equal", + document: "a: frog", + expression: `select(.b == .c)`, + expected: []string{ + "D0, P[], (!!map)::a: frog\n", + }, + }, } func TestEqualOperatorScenarios(t *testing.T) { diff --git a/pkg/yqlib/operator_keys.go b/pkg/yqlib/operator_keys.go index d6cf112e..bbb9a5d8 100644 --- a/pkg/yqlib/operator_keys.go +++ b/pkg/yqlib/operator_keys.go @@ -53,7 +53,6 @@ func keysOperator(d *dataTreeNavigator, context Context, expressionNode *Express return Context{}, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", candidate.Tag) } - // result := candidate.CreateReplacement(targetNode) results.PushBack(targetNode) } diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go index caeb33ac..56340cbb 100644 --- a/pkg/yqlib/operators_test.go +++ b/pkg/yqlib/operators_test.go @@ -32,7 +32,7 @@ type expressionScenario struct { } func TestMain(m *testing.M) { - logging.SetLevel(logging.DEBUG, "") + logging.SetLevel(logging.ERROR, "") Now = func() time.Time { return time.Date(2021, time.May, 19, 1, 2, 3, 4, time.UTC) }