mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	value parse test
This commit is contained in:
		
							parent
							
								
									60511f5f92
								
							
						
					
					
						commit
						5e544a5b7e
					
				| @ -628,81 +628,6 @@ func TestDataTreeNavigatorArraySimple(t *testing.T) { | ||||
| 	test.AssertResult(t, expected, resultsToString(results)) | ||||
| } | ||||
| 
 | ||||
| func TestDataTreeNavigatorSimpleAssignCmd(t *testing.T) { | ||||
| 
 | ||||
| 	nodes := readDoc(t, `a:  | ||||
|   b: apple`) | ||||
| 
 | ||||
| 	path, errPath := treeCreator.ParsePath(`.a.b |= "frog"`) | ||||
| 	if errPath != nil { | ||||
| 		t.Error(errPath) | ||||
| 	} | ||||
| 	results, errNav := treeNavigator.GetMatchingNodes(nodes, path) | ||||
| 
 | ||||
| 	if errNav != nil { | ||||
| 		t.Error(errNav) | ||||
| 	} | ||||
| 
 | ||||
| 	expected := ` | ||||
| -- Node -- | ||||
|   Document 0, path: [a b] | ||||
|   Tag: !!str, Kind: ScalarNode, Anchor:  | ||||
|   frog | ||||
| ` | ||||
| 
 | ||||
| 	test.AssertResult(t, expected, resultsToString(results)) | ||||
| } | ||||
| 
 | ||||
| func TestDataTreeNavigatorSimpleAssignNumberCmd(t *testing.T) { | ||||
| 
 | ||||
| 	nodes := readDoc(t, `a:  | ||||
|   b: apple`) | ||||
| 
 | ||||
| 	path, errPath := treeCreator.ParsePath(`.a.b |= 5`) | ||||
| 	if errPath != nil { | ||||
| 		t.Error(errPath) | ||||
| 	} | ||||
| 	results, errNav := treeNavigator.GetMatchingNodes(nodes, path) | ||||
| 
 | ||||
| 	if errNav != nil { | ||||
| 		t.Error(errNav) | ||||
| 	} | ||||
| 
 | ||||
| 	expected := ` | ||||
| -- Node -- | ||||
|   Document 0, path: [a b] | ||||
|   Tag: !!int, Kind: ScalarNode, Anchor:  | ||||
|   5 | ||||
| ` | ||||
| 
 | ||||
| 	test.AssertResult(t, expected, resultsToString(results)) | ||||
| } | ||||
| 
 | ||||
| func TestDataTreeNavigatorSimpleAssignFloatCmd(t *testing.T) { | ||||
| 
 | ||||
| 	nodes := readDoc(t, `a:  | ||||
|   b: apple`) | ||||
| 
 | ||||
| 	path, errPath := treeCreator.ParsePath(`.a.b |= 3.142`) | ||||
| 	if errPath != nil { | ||||
| 		t.Error(errPath) | ||||
| 	} | ||||
| 	results, errNav := treeNavigator.GetMatchingNodes(nodes, path) | ||||
| 
 | ||||
| 	if errNav != nil { | ||||
| 		t.Error(errNav) | ||||
| 	} | ||||
| 
 | ||||
| 	expected := ` | ||||
| -- Node -- | ||||
|   Document 0, path: [a b] | ||||
|   Tag: !!float, Kind: ScalarNode, Anchor:  | ||||
|   3.142 | ||||
| ` | ||||
| 
 | ||||
| 	test.AssertResult(t, expected, resultsToString(results)) | ||||
| } | ||||
| 
 | ||||
| func TestDataTreeNavigatorSimpleAssignBooleanCmd(t *testing.T) { | ||||
| 
 | ||||
| 	nodes := readDoc(t, `a:  | ||||
|  | ||||
							
								
								
									
										27
									
								
								pkg/yqlib/treeops/operator_assign.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								pkg/yqlib/treeops/operator_assign.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| package treeops | ||||
| 
 | ||||
| import "github.com/elliotchance/orderedmap" | ||||
| 
 | ||||
| func AssignOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) { | ||||
| 	lhs, err := d.getMatchingNodes(matchingNodes, pathNode.Lhs) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for el := lhs.Front(); el != nil; el = el.Next() { | ||||
| 		candidate := el.Value.(*CandidateNode) | ||||
| 
 | ||||
| 		rhs, err := d.getMatchingNodes(nodeToMap(candidate), pathNode.Rhs) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		// grab the first value | ||||
| 		first := rhs.Front() | ||||
| 
 | ||||
| 		if first != nil { | ||||
| 			candidate.UpdateFrom(first.Value.(*CandidateNode)) | ||||
| 		} | ||||
| 	} | ||||
| 	return matchingNodes, nil | ||||
| } | ||||
							
								
								
									
										62
									
								
								pkg/yqlib/treeops/operator_assign_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								pkg/yqlib/treeops/operator_assign_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | ||||
| package treeops | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| var assignOperatorScenarios = []expressionScenario{ | ||||
| 	{ | ||||
| 		document:   `{a: {b: apple}}`, | ||||
| 		expression: `.a.b |= "frog"`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!map)::{a: {b: frog}}\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   `{a: {b: apple}}`, | ||||
| 		expression: `.a.b | (. |= "frog")`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[a b], (!!str)::frog\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   `{a: {b: apple}}`, | ||||
| 		expression: `.a.b |= 5`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!map)::{a: {b: 5}}\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   `{a: {b: apple}}`, | ||||
| 		expression: `.a.b |= 3.142`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!map)::{a: {b: 3.142}}\n", | ||||
| 		}, | ||||
| 		// 	document:   `{}`, | ||||
| 		// 	expression: `["cat", "dog"]`, | ||||
| 		// 	expected: []string{ | ||||
| 		// 		"D0, P[], (!!seq)::- cat\n- dog\n", | ||||
| 		// 	}, | ||||
| 		// }, { | ||||
| 		// 	document:   `{}`, | ||||
| 		// 	expression: `1 | collect`, | ||||
| 		// 	expected: []string{ | ||||
| 		// 		"D0, P[], (!!seq)::- 1\n", | ||||
| 		// 	}, | ||||
| 		// }, { | ||||
| 		// 	document:   `[1,2,3]`, | ||||
| 		// 	expression: `[.[]]`, | ||||
| 		// 	expected: []string{ | ||||
| 		// 		"D0, P[], (!!seq)::- 1\n- 2\n- 3\n", | ||||
| 		// 	}, | ||||
| 		// }, { | ||||
| 		// 	document:   `a: {b: [1,2,3]}`, | ||||
| 		// 	expression: `[.a.b[]]`, | ||||
| 		// 	expected: []string{ | ||||
| 		// 		"D0, P[a b], (!!seq)::- 1\n- 2\n- 3\n", | ||||
| 		// 	}, | ||||
| 	}, | ||||
| } | ||||
| 
 | ||||
| func TestAssignOperatorScenarios(t *testing.T) { | ||||
| 	for _, tt := range assignOperatorScenarios { | ||||
| 		testScenario(t, &tt) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										75
									
								
								pkg/yqlib/treeops/operator_value_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								pkg/yqlib/treeops/operator_value_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| package treeops | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| var valueOperatorScenarios = []expressionScenario{ | ||||
| 	{ | ||||
| 		document:   ``, | ||||
| 		expression: `1`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!int)::1\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `-1`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!int)::-1\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `1.2`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!float)::1.2\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `-5.2e11`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!float)::-5.2e11\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `5e-10`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!float)::5e-10\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `"cat"`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!str)::cat\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `"1.3"`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!str)::\"1.3\"\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `"true"`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!str)::\"true\"\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `true`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!bool)::true\n", | ||||
| 		}, | ||||
| 	}, { | ||||
| 		document:   ``, | ||||
| 		expression: `false`, | ||||
| 		expected: []string{ | ||||
| 			"D0, P[], (!!bool)::false\n", | ||||
| 		}, | ||||
| 	}, | ||||
| } | ||||
| 
 | ||||
| func TestValueOperatorScenarios(t *testing.T) { | ||||
| 	for _, tt := range valueOperatorScenarios { | ||||
| 		testScenario(t, &tt) | ||||
| 	} | ||||
| } | ||||
| @ -32,30 +32,6 @@ func nodeToMap(candidate *CandidateNode) *orderedmap.OrderedMap { | ||||
| 	return elMap | ||||
| } | ||||
| 
 | ||||
| func AssignOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) { | ||||
| 	lhs, err := d.getMatchingNodes(matchingNodes, pathNode.Lhs) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for el := lhs.Front(); el != nil; el = el.Next() { | ||||
| 		candidate := el.Value.(*CandidateNode) | ||||
| 
 | ||||
| 		rhs, err := d.getMatchingNodes(nodeToMap(candidate), pathNode.Rhs) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		// grab the first value | ||||
| 		first := rhs.Front() | ||||
| 
 | ||||
| 		if first != nil { | ||||
| 			candidate.UpdateFrom(first.Value.(*CandidateNode)) | ||||
| 		} | ||||
| 	} | ||||
| 	return lhs, nil | ||||
| } | ||||
| 
 | ||||
| func IntersectionOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) { | ||||
| 	lhs, err := d.getMatchingNodes(matchingNodes, pathNode.Lhs) | ||||
| 	if err != nil { | ||||
|  | ||||
| @ -76,6 +76,17 @@ func numberValue() lex.Action { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func floatValue() lex.Action { | ||||
| 	return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { | ||||
| 		var numberString = string(m.Bytes) | ||||
| 		var number, errParsingInt = strconv.ParseFloat(numberString, 64) // nolint | ||||
| 		if errParsingInt != nil { | ||||
| 			return nil, errParsingInt | ||||
| 		} | ||||
| 		return &Token{PathElementType: Value, OperationType: None, Value: number, StringValue: numberString}, nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func booleanValue(val bool) lex.Action { | ||||
| 	return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { | ||||
| 		return &Token{PathElementType: Value, OperationType: None, Value: val, StringValue: string(m.Bytes)}, nil | ||||
| @ -111,7 +122,7 @@ func initLexer() (*lex.Lexer, error) { | ||||
| 	lexer.Add([]byte(`length`), opToken(Length)) | ||||
| 	lexer.Add([]byte(`select`), opToken(Select)) | ||||
| 	lexer.Add([]byte(`or`), opToken(Or)) | ||||
| 	lexer.Add([]byte(`and`), opToken(And)) | ||||
| 	// lexer.Add([]byte(`and`), opToken()) | ||||
| 	lexer.Add([]byte(`collect`), opToken(Collect)) | ||||
| 
 | ||||
| 	lexer.Add([]byte(`\s*==\s*`), opToken(Equals)) | ||||
| @ -131,7 +142,9 @@ func initLexer() (*lex.Lexer, error) { | ||||
| 
 | ||||
| 	lexer.Add([]byte(`\|`), opToken(Pipe)) | ||||
| 
 | ||||
| 	lexer.Add([]byte(`-?[0-9]+`), numberValue()) | ||||
| 	lexer.Add([]byte(`-?\d+(\.\d+)`), floatValue()) | ||||
| 	lexer.Add([]byte(`-?[1-9](\.\d+)?[Ee][-+]?\d+`), floatValue()) | ||||
| 	lexer.Add([]byte(`-?\d+`), numberValue()) | ||||
| 
 | ||||
| 	lexer.Add([]byte(`[Tt][Rr][Uu][Ee]`), booleanValue(true)) | ||||
| 	lexer.Add([]byte(`[Ff][Aa][Ll][Ss][Ee]`), booleanValue(false)) | ||||
|  | ||||
| @ -1,46 +0,0 @@ | ||||
| package yqlib | ||||
| 
 | ||||
| import ( | ||||
| 	yaml "gopkg.in/yaml.v3" | ||||
| ) | ||||
| 
 | ||||
| type ValueParser interface { | ||||
| 	Parse(argument string, customTag string, customStyle string, anchorName string, createAlias bool) *yaml.Node | ||||
| } | ||||
| 
 | ||||
| type valueParser struct { | ||||
| } | ||||
| 
 | ||||
| func NewValueParser() ValueParser { | ||||
| 	return &valueParser{} | ||||
| } | ||||
| 
 | ||||
| func (v *valueParser) Parse(argument string, customTag string, customStyle string, anchorName string, createAlias bool) *yaml.Node { | ||||
| 	var style yaml.Style | ||||
| 	if customStyle == "tagged" { | ||||
| 		style = yaml.TaggedStyle | ||||
| 	} else if customStyle == "double" { | ||||
| 		style = yaml.DoubleQuotedStyle | ||||
| 	} else if customStyle == "single" { | ||||
| 		style = yaml.SingleQuotedStyle | ||||
| 	} else if customStyle == "literal" { | ||||
| 		style = yaml.LiteralStyle | ||||
| 	} else if customStyle == "folded" { | ||||
| 		style = yaml.FoldedStyle | ||||
| 	} else if customStyle == "flow" { | ||||
| 		style = yaml.FlowStyle | ||||
| 	} else if customStyle != "" { | ||||
| 		log.Error("Unknown style %v, ignoring", customStyle) | ||||
| 	} | ||||
| 	if argument == "[]" { | ||||
| 		return &yaml.Node{Tag: "!!seq", Kind: yaml.SequenceNode, Style: style} | ||||
| 	} | ||||
| 
 | ||||
| 	kind := yaml.ScalarNode | ||||
| 
 | ||||
| 	if createAlias { | ||||
| 		kind = yaml.AliasNode | ||||
| 	} | ||||
| 
 | ||||
| 	return &yaml.Node{Value: argument, Tag: customTag, Kind: kind, Style: style, Anchor: anchorName} | ||||
| } | ||||
| @ -1,65 +0,0 @@ | ||||
| package yqlib | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/mikefarah/yq/v3/test" | ||||
| 	yaml "gopkg.in/yaml.v3" | ||||
| ) | ||||
| 
 | ||||
| var parseStyleTests = []struct { | ||||
| 	customStyle   string | ||||
| 	expectedStyle yaml.Style | ||||
| }{ | ||||
| 	{"", 0}, | ||||
| 	{"tagged", yaml.TaggedStyle}, | ||||
| 	{"double", yaml.DoubleQuotedStyle}, | ||||
| 	{"single", yaml.SingleQuotedStyle}, | ||||
| 	{"folded", yaml.FoldedStyle}, | ||||
| 	{"flow", yaml.FlowStyle}, | ||||
| 	{"literal", yaml.LiteralStyle}, | ||||
| } | ||||
| 
 | ||||
| func TestValueParserStyleTag(t *testing.T) { | ||||
| 	for _, tt := range parseStyleTests { | ||||
| 		actual := NewValueParser().Parse("cat", "", tt.customStyle, "", false) | ||||
| 		test.AssertResultWithContext(t, tt.expectedStyle, actual.Style, tt.customStyle) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var parseValueTests = []struct { | ||||
| 	argument        string | ||||
| 	customTag       string | ||||
| 	expectedTag     string | ||||
| 	testDescription string | ||||
| }{ | ||||
| 	{"true", "!!str", "!!str", "boolean forced as string"}, | ||||
| 	{"3", "!!int", "!!int", "int"}, | ||||
| 	{"cat", "", "", "default"}, | ||||
| } | ||||
| 
 | ||||
| func TestValueParserParse(t *testing.T) { | ||||
| 	for _, tt := range parseValueTests { | ||||
| 		actual := NewValueParser().Parse(tt.argument, tt.customTag, "", "", false) | ||||
| 		test.AssertResultWithContext(t, tt.argument, actual.Value, tt.testDescription) | ||||
| 		test.AssertResultWithContext(t, tt.expectedTag, actual.Tag, tt.testDescription) | ||||
| 		test.AssertResult(t, yaml.ScalarNode, actual.Kind) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestValueParserParseEmptyArray(t *testing.T) { | ||||
| 	actual := NewValueParser().Parse("[]", "", "", "", false) | ||||
| 	test.AssertResult(t, "!!seq", actual.Tag) | ||||
| 	test.AssertResult(t, yaml.SequenceNode, actual.Kind) | ||||
| } | ||||
| 
 | ||||
| func TestValueParserParseAlias(t *testing.T) { | ||||
| 	actual := NewValueParser().Parse("bob", "", "", "", true) | ||||
| 	test.AssertResult(t, "bob", actual.Value) | ||||
| 	test.AssertResult(t, yaml.AliasNode, actual.Kind) | ||||
| } | ||||
| 
 | ||||
| func TestValueParserAnchorname(t *testing.T) { | ||||
| 	actual := NewValueParser().Parse("caterpillar", "", "", "foo", false) | ||||
| 	test.AssertResult(t, "foo", actual.Anchor) | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user