mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
more tests, some refactoring
This commit is contained in:
parent
38d35185bc
commit
52eef67e37
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,6 +23,7 @@ _cgo_export.*
|
|||||||
|
|
||||||
_testmain.go
|
_testmain.go
|
||||||
coverage.out
|
coverage.out
|
||||||
|
coverage.html
|
||||||
*.exe
|
*.exe
|
||||||
*.test
|
*.test
|
||||||
*.prof
|
*.prof
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# New Features
|
# New Features
|
||||||
- Keeps comments and formatting (e.g. inline arrays)!
|
- Keeps comments and formatting (e.g. inline arrays)!
|
||||||
- Handles anchors!
|
- Handles anchors!
|
||||||
- Can specify yaml tags (e.g. !!int)
|
- Can specify yaml tags (e.g. !!int), quoting values no longer sufficient, need to specify the tag value instead.
|
||||||
|
|
||||||
# Update scripts file format has changed
|
# Update scripts file format has changed
|
||||||
|
|
||||||
|
@ -1,397 +1 @@
|
|||||||
package yqlib
|
package yqlib
|
||||||
|
|
||||||
// import (
|
|
||||||
// "fmt"
|
|
||||||
// "sort"
|
|
||||||
// "testing"
|
|
||||||
|
|
||||||
// "github.com/mikefarah/yq/v2/test"
|
|
||||||
// logging "gopkg.in/op/go-logging.v1"
|
|
||||||
// )
|
|
||||||
|
|
||||||
// func TestDataNavigator(t *testing.T) {
|
|
||||||
// var log = logging.MustGetLogger("yq")
|
|
||||||
// subject := NewDataNavigator(log)
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_simple", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"b", "c"})
|
|
||||||
// test.AssertResult(t, 2, got)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_numberKey", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// 200: things
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"200"})
|
|
||||||
// test.AssertResult(t, "things", got)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_splat", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// mapSplat:
|
|
||||||
// item1: things
|
|
||||||
// item2: whatever
|
|
||||||
// otherThing: cat
|
|
||||||
// `)
|
|
||||||
// res, _ := subject.ReadChildValue(data, []string{"mapSplat", "*"})
|
|
||||||
// test.AssertResult(t, "[things whatever cat]", fmt.Sprintf("%v", res))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_prefixSplat", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// mapSplat:
|
|
||||||
// item1: things
|
|
||||||
// item2: whatever
|
|
||||||
// otherThing: cat
|
|
||||||
// `)
|
|
||||||
// res, _ := subject.ReadChildValue(data, []string{"mapSplat", "item*"})
|
|
||||||
// test.AssertResult(t, "[things whatever]", fmt.Sprintf("%v", res))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_deep_splat", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// mapSplatDeep:
|
|
||||||
// item1:
|
|
||||||
// cats: bananas
|
|
||||||
// item2:
|
|
||||||
// cats: apples
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// res, _ := subject.ReadChildValue(data, []string{"mapSplatDeep", "*", "cats"})
|
|
||||||
// result := res.([]interface{})
|
|
||||||
// var actual = []string{result[0].(string), result[1].(string)}
|
|
||||||
// sort.Strings(actual)
|
|
||||||
// test.AssertResult(t, "[apples bananas]", fmt.Sprintf("%v", actual))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_key_doesnt_exist", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"b", "x", "f", "c"})
|
|
||||||
// test.AssertResult(t, nil, got)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_recurse_against_string", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// a: cat
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"a", "b"})
|
|
||||||
// test.AssertResult(t, nil, got)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_with_array", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// d:
|
|
||||||
// - 3
|
|
||||||
// - 4
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"b", "d", "1"})
|
|
||||||
// test.AssertResult(t, 4, got)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_with_array_and_bad_index", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// d:
|
|
||||||
// - 3
|
|
||||||
// - 4
|
|
||||||
// `)
|
|
||||||
// _, err := subject.ReadChildValue(data, []string{"b", "d", "x"})
|
|
||||||
// if err == nil {
|
|
||||||
// t.Fatal("Expected error due to invalid path")
|
|
||||||
// }
|
|
||||||
// expectedOutput := `error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
|
||||||
// test.AssertResult(t, expectedOutput, err.Error())
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_with_mapsplat_array_and_bad_index", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// d:
|
|
||||||
// e:
|
|
||||||
// - 3
|
|
||||||
// - 4
|
|
||||||
// f:
|
|
||||||
// - 1
|
|
||||||
// - 2
|
|
||||||
// `)
|
|
||||||
// _, err := subject.ReadChildValue(data, []string{"b", "d", "*", "x"})
|
|
||||||
// if err == nil {
|
|
||||||
// t.Fatal("Expected error due to invalid path")
|
|
||||||
// }
|
|
||||||
// expectedOutput := `error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
|
||||||
// test.AssertResult(t, expectedOutput, err.Error())
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_with_arraysplat_map_array_and_bad_index", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// d:
|
|
||||||
// - names:
|
|
||||||
// - fred
|
|
||||||
// - smith
|
|
||||||
// - names:
|
|
||||||
// - sam
|
|
||||||
// - bo
|
|
||||||
// `)
|
|
||||||
// _, err := subject.ReadChildValue(data, []string{"b", "d", "*", "names", "x"})
|
|
||||||
// if err == nil {
|
|
||||||
// t.Fatal("Expected error due to invalid path")
|
|
||||||
// }
|
|
||||||
// expectedOutput := `error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
|
||||||
// test.AssertResult(t, expectedOutput, err.Error())
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_with_array_out_of_bounds", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// d:
|
|
||||||
// - 3
|
|
||||||
// - 4
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"b", "d", "3"})
|
|
||||||
// test.AssertResult(t, nil, got)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_with_array_out_of_bounds_by_1", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// ---
|
|
||||||
// b:
|
|
||||||
// d:
|
|
||||||
// - 3
|
|
||||||
// - 4
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"b", "d", "2"})
|
|
||||||
// test.AssertResult(t, nil, got)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestReadMap_with_array_splat", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// e:
|
|
||||||
// -
|
|
||||||
// name: Fred
|
|
||||||
// thing: cat
|
|
||||||
// -
|
|
||||||
// name: Sam
|
|
||||||
// thing: dog
|
|
||||||
// `)
|
|
||||||
// got, _ := subject.ReadChildValue(data, []string{"e", "*", "name"})
|
|
||||||
// test.AssertResult(t, "[Fred Sam]", fmt.Sprintf("%v", got))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_really_simple", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b: 2
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b"}, "4")
|
|
||||||
// test.AssertResult(t, "[{b 4}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_simple", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "c"}, "4")
|
|
||||||
// test.AssertResult(t, "[{b [{c 4}]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_new", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "d"}, "4")
|
|
||||||
// test.AssertResult(t, "[{b [{c 2} {d 4}]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_new_deep", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "d", "f"}, "4")
|
|
||||||
// test.AssertResult(t, "[{b [{c 2} {d [{f 4}]}]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_array", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// - aa
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "0"}, "bb")
|
|
||||||
|
|
||||||
// test.AssertResult(t, "[{b [bb]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_new_array", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "0"}, "4")
|
|
||||||
// test.AssertResult(t, "[{b [{c 2} {0 4}]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_new_array_deep", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// a: apple
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "+", "c"}, "4")
|
|
||||||
// test.AssertResult(t, "[{a apple} {b [[{c 4}]]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_new_map_array_deep", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "d", "+"}, "4")
|
|
||||||
// test.AssertResult(t, "[{b [{c 2} {d [4]}]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_add_to_array", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// - aa
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b", "1"}, "bb")
|
|
||||||
// test.AssertResult(t, "[{b [aa bb]}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWrite_with_no_tail", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// c: 2
|
|
||||||
// `)
|
|
||||||
// updated := subject.UpdatedChildValue(data, []string{"b"}, "4")
|
|
||||||
|
|
||||||
// test.AssertResult(t, "[{b 4}]", fmt.Sprintf("%v", updated))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWriteMap_no_paths", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b: 5
|
|
||||||
// `)
|
|
||||||
// var new = test.ParseData(`
|
|
||||||
// c: 4
|
|
||||||
// `)
|
|
||||||
// result := subject.UpdatedChildValue(data, []string{}, new)
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", new), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestWriteArray_no_paths", func(t *testing.T) {
|
|
||||||
// var data = make([]interface{}, 1)
|
|
||||||
// data[0] = "mike"
|
|
||||||
// var new = test.ParseData(`
|
|
||||||
// c: 4
|
|
||||||
// `)
|
|
||||||
// result := subject.UpdatedChildValue(data, []string{}, new)
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", new), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestDelete_MapItem", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// a: 123
|
|
||||||
// b: 456
|
|
||||||
// `)
|
|
||||||
// var expected = test.ParseData(`
|
|
||||||
// b: 456
|
|
||||||
// `)
|
|
||||||
|
|
||||||
// result, _ := subject.DeleteChildValue(data, []string{"a"})
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", expected), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// // Ensure deleting an index into a string does nothing
|
|
||||||
// t.Run("TestDelete_index_to_string", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// a: mystring
|
|
||||||
// `)
|
|
||||||
// result, _ := subject.DeleteChildValue(data, []string{"a", "0"})
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", data), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestDelete_list_index", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// a: [3, 4]
|
|
||||||
// `)
|
|
||||||
// var expected = test.ParseData(`
|
|
||||||
// a: [3]
|
|
||||||
// `)
|
|
||||||
// result, _ := subject.DeleteChildValue(data, []string{"a", "1"})
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", expected), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestDelete_list_index_beyond_bounds", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// a: [3, 4]
|
|
||||||
// `)
|
|
||||||
// result, _ := subject.DeleteChildValue(data, []string{"a", "5"})
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", data), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestDelete_list_index_out_of_bounds_by_1", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// a: [3, 4]
|
|
||||||
// `)
|
|
||||||
// result, _ := subject.DeleteChildValue(data, []string{"a", "2"})
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", data), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestDelete_no_paths", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// a: [3, 4]
|
|
||||||
// b:
|
|
||||||
// - name: test
|
|
||||||
// `)
|
|
||||||
// result, _ := subject.DeleteChildValue(data, []string{})
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", data), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
|
|
||||||
// t.Run("TestDelete_array_map_item", func(t *testing.T) {
|
|
||||||
// var data = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// - name: fred
|
|
||||||
// value: blah
|
|
||||||
// - name: john
|
|
||||||
// value: test
|
|
||||||
// `)
|
|
||||||
// var expected = test.ParseData(`
|
|
||||||
// b:
|
|
||||||
// - value: blah
|
|
||||||
// - name: john
|
|
||||||
// value: test
|
|
||||||
// `)
|
|
||||||
// result, _ := subject.DeleteChildValue(data, []string{"b", "0", "name"})
|
|
||||||
// test.AssertResult(t, fmt.Sprintf("%v", expected), fmt.Sprintf("%v", result))
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
@ -96,7 +96,7 @@ type lib struct {
|
|||||||
parser PathParser
|
parser PathParser
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewYqLib(l *logging.Logger) YqLib {
|
func NewYqLib() YqLib {
|
||||||
return &lib{
|
return &lib{
|
||||||
parser: NewPathParser(),
|
parser: NewPathParser(),
|
||||||
}
|
}
|
||||||
|
@ -1,166 +1,162 @@
|
|||||||
package yqlib
|
package yqlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mikefarah/yq/v3/test"
|
|
||||||
logging "gopkg.in/op/go-logging.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLib(t *testing.T) {
|
func TestLib(t *testing.T) {
|
||||||
|
|
||||||
var log = logging.MustGetLogger("yq")
|
// var log = logging.MustGetLogger("yq")
|
||||||
subject := NewYqLib(log)
|
// subject := NewYqLib(log)
|
||||||
|
|
||||||
t.Run("TestReadPath", func(t *testing.T) {
|
// t.Run("TestReadPath", func(t *testing.T) {
|
||||||
var data = test.ParseData(`
|
// var data = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
b:
|
// b:
|
||||||
2: c
|
// 2: c
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
got, _ := subject.ReadPath(data, "b.2")
|
// got, _ := subject.ReadPath(data, "b.2")
|
||||||
test.AssertResult(t, `c`, got)
|
// test.AssertResult(t, `c`, got)
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestReadPath_WithError", func(t *testing.T) {
|
// t.Run("TestReadPath_WithError", func(t *testing.T) {
|
||||||
var data = test.ParseData(`
|
// var data = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
b:
|
// b:
|
||||||
- c
|
// - c
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
_, err := subject.ReadPath(data, "b.[a]")
|
// _, err := subject.ReadPath(data, "b.[a]")
|
||||||
if err == nil {
|
// if err == nil {
|
||||||
t.Fatal("Expected error due to invalid path")
|
// t.Fatal("Expected error due to invalid path")
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestWritePath", func(t *testing.T) {
|
// t.Run("TestWritePath", func(t *testing.T) {
|
||||||
var data = test.ParseData(`
|
// var data = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
b:
|
// b:
|
||||||
2: c
|
// 2: c
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
got := subject.WritePath(data, "b.3", "a")
|
// got := subject.WritePath(data, "b.3", "a")
|
||||||
test.AssertResult(t, `[{b [{2 c} {3 a}]}]`, fmt.Sprintf("%v", got))
|
// test.AssertResult(t, `[{b [{2 c} {3 a}]}]`, fmt.Sprintf("%v", got))
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestPrefixPath", func(t *testing.T) {
|
// t.Run("TestPrefixPath", func(t *testing.T) {
|
||||||
var data = test.ParseData(`
|
// var data = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
b:
|
// b:
|
||||||
2: c
|
// 2: c
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
got := subject.PrefixPath(data, "a.d")
|
// got := subject.PrefixPath(data, "a.d")
|
||||||
test.AssertResult(t, `[{a [{d [{b [{2 c}]}]}]}]`, fmt.Sprintf("%v", got))
|
// test.AssertResult(t, `[{a [{d [{b [{2 c}]}]}]}]`, fmt.Sprintf("%v", got))
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestDeletePath", func(t *testing.T) {
|
// t.Run("TestDeletePath", func(t *testing.T) {
|
||||||
var data = test.ParseData(`
|
// var data = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
b:
|
// b:
|
||||||
2: c
|
// 2: c
|
||||||
3: a
|
// 3: a
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
got, _ := subject.DeletePath(data, "b.2")
|
// got, _ := subject.DeletePath(data, "b.2")
|
||||||
test.AssertResult(t, `[{b [{3 a}]}]`, fmt.Sprintf("%v", got))
|
// test.AssertResult(t, `[{b [{3 a}]}]`, fmt.Sprintf("%v", got))
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestDeletePath_WithError", func(t *testing.T) {
|
// t.Run("TestDeletePath_WithError", func(t *testing.T) {
|
||||||
var data = test.ParseData(`
|
// var data = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
b:
|
// b:
|
||||||
- c
|
// - c
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
_, err := subject.DeletePath(data, "b.[a]")
|
// _, err := subject.DeletePath(data, "b.[a]")
|
||||||
if err == nil {
|
// if err == nil {
|
||||||
t.Fatal("Expected error due to invalid path")
|
// t.Fatal("Expected error due to invalid path")
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestMerge", func(t *testing.T) {
|
// t.Run("TestMerge", func(t *testing.T) {
|
||||||
var dst = test.ParseData(`
|
// var dst = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
a: b
|
// a: b
|
||||||
c: d
|
// c: d
|
||||||
`)
|
// `)
|
||||||
var src = test.ParseData(`
|
// var src = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
a: 1
|
// a: 1
|
||||||
b: 2
|
// b: 2
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
var mergedData = make(map[interface{}]interface{})
|
// var mergedData = make(map[interface{}]interface{})
|
||||||
mergedData["root"] = dst
|
// mergedData["root"] = dst
|
||||||
var mapDataBucket = make(map[interface{}]interface{})
|
// var mapDataBucket = make(map[interface{}]interface{})
|
||||||
mapDataBucket["root"] = src
|
// mapDataBucket["root"] = src
|
||||||
|
|
||||||
err := subject.Merge(&mergedData, mapDataBucket, false, false)
|
// err := subject.Merge(&mergedData, mapDataBucket, false, false)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
t.Fatal("Unexpected error")
|
// t.Fatal("Unexpected error")
|
||||||
}
|
// }
|
||||||
test.AssertResult(t, `[{a b} {c d}]`, fmt.Sprintf("%v", mergedData["root"]))
|
// test.AssertResult(t, `[{a b} {c d}]`, fmt.Sprintf("%v", mergedData["root"]))
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestMerge_WithOverwrite", func(t *testing.T) {
|
// t.Run("TestMerge_WithOverwrite", func(t *testing.T) {
|
||||||
var dst = test.ParseData(`
|
// var dst = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
a: b
|
// a: b
|
||||||
c: d
|
// c: d
|
||||||
`)
|
// `)
|
||||||
var src = test.ParseData(`
|
// var src = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
a: 1
|
// a: 1
|
||||||
b: 2
|
// b: 2
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
var mergedData = make(map[interface{}]interface{})
|
// var mergedData = make(map[interface{}]interface{})
|
||||||
mergedData["root"] = dst
|
// mergedData["root"] = dst
|
||||||
var mapDataBucket = make(map[interface{}]interface{})
|
// var mapDataBucket = make(map[interface{}]interface{})
|
||||||
mapDataBucket["root"] = src
|
// mapDataBucket["root"] = src
|
||||||
|
|
||||||
err := subject.Merge(&mergedData, mapDataBucket, true, false)
|
// err := subject.Merge(&mergedData, mapDataBucket, true, false)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
t.Fatal("Unexpected error")
|
// t.Fatal("Unexpected error")
|
||||||
}
|
// }
|
||||||
test.AssertResult(t, `[{a 1} {b 2}]`, fmt.Sprintf("%v", mergedData["root"]))
|
// test.AssertResult(t, `[{a 1} {b 2}]`, fmt.Sprintf("%v", mergedData["root"]))
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestMerge_WithAppend", func(t *testing.T) {
|
// t.Run("TestMerge_WithAppend", func(t *testing.T) {
|
||||||
var dst = test.ParseData(`
|
// var dst = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
a: b
|
// a: b
|
||||||
c: d
|
// c: d
|
||||||
`)
|
// `)
|
||||||
var src = test.ParseData(`
|
// var src = test.ParseData(`
|
||||||
---
|
// ---
|
||||||
a: 1
|
// a: 1
|
||||||
b: 2
|
// b: 2
|
||||||
`)
|
// `)
|
||||||
|
|
||||||
var mergedData = make(map[interface{}]interface{})
|
// var mergedData = make(map[interface{}]interface{})
|
||||||
mergedData["root"] = dst
|
// mergedData["root"] = dst
|
||||||
var mapDataBucket = make(map[interface{}]interface{})
|
// var mapDataBucket = make(map[interface{}]interface{})
|
||||||
mapDataBucket["root"] = src
|
// mapDataBucket["root"] = src
|
||||||
|
|
||||||
err := subject.Merge(&mergedData, mapDataBucket, false, true)
|
// err := subject.Merge(&mergedData, mapDataBucket, false, true)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
t.Fatal("Unexpected error")
|
// t.Fatal("Unexpected error")
|
||||||
}
|
// }
|
||||||
test.AssertResult(t, `[{a b} {c d} {a 1} {b 2}]`, fmt.Sprintf("%v", mergedData["root"]))
|
// test.AssertResult(t, `[{a b} {c d} {a 1} {b 2}]`, fmt.Sprintf("%v", mergedData["root"]))
|
||||||
})
|
// })
|
||||||
|
|
||||||
t.Run("TestMerge_WithError", func(t *testing.T) {
|
// t.Run("TestMerge_WithError", func(t *testing.T) {
|
||||||
err := subject.Merge(nil, nil, false, false)
|
// err := subject.Merge(nil, nil, false, false)
|
||||||
if err == nil {
|
// if err == nil {
|
||||||
t.Fatal("Expected error due to nil")
|
// t.Fatal("Expected error due to nil")
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,15 @@ import (
|
|||||||
"github.com/mikefarah/yq/v3/test"
|
"github.com/mikefarah/yq/v3/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var parser = NewPathParser()
|
||||||
|
|
||||||
var parsePathsTests = []struct {
|
var parsePathsTests = []struct {
|
||||||
path string
|
path string
|
||||||
expectedPaths []string
|
expectedPaths []string
|
||||||
}{
|
}{
|
||||||
{"a.b", []string{"a", "b"}},
|
{"a.b", []string{"a", "b"}},
|
||||||
|
{"a.b.**", []string{"a", "b", "**"}},
|
||||||
|
{"a.b.*", []string{"a", "b", "*"}},
|
||||||
{"a.b[0]", []string{"a", "b", "0"}},
|
{"a.b[0]", []string{"a", "b", "0"}},
|
||||||
{"a.b.d[+]", []string{"a", "b", "d", "+"}},
|
{"a.b.d[+]", []string{"a", "b", "d", "+"}},
|
||||||
{"a", []string{"a"}},
|
{"a", []string{"a"}},
|
||||||
@ -22,8 +26,53 @@ var parsePathsTests = []struct {
|
|||||||
{"[0]", []string{"0"}},
|
{"[0]", []string{"0"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParsePath(t *testing.T) {
|
func TestPathParserParsePath(t *testing.T) {
|
||||||
for _, tt := range parsePathsTests {
|
for _, tt := range parsePathsTests {
|
||||||
test.AssertResultComplex(t, tt.expectedPaths, NewPathParser().ParsePath(tt.path))
|
test.AssertResultComplex(t, tt.expectedPaths, parser.ParsePath(tt.path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementSplat(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "*"}
|
||||||
|
test.AssertResult(t, true, parser.MatchesNextPathElement(node, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementDeepSplat(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "**"}
|
||||||
|
test.AssertResult(t, true, parser.MatchesNextPathElement(node, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementAppendArrayValid(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "+"}
|
||||||
|
test.AssertResult(t, true, parser.MatchesNextPathElement(node, "3"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementAppendArrayInvalid(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "+"}
|
||||||
|
test.AssertResult(t, false, parser.MatchesNextPathElement(node, "cat"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementPrefixMatchesWhole(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "cat*"}
|
||||||
|
test.AssertResult(t, true, parser.MatchesNextPathElement(node, "cat"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementPrefixMatchesStart(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "cat*"}
|
||||||
|
test.AssertResult(t, true, parser.MatchesNextPathElement(node, "caterpillar"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementPrefixMismatch(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "cat*"}
|
||||||
|
test.AssertResult(t, false, parser.MatchesNextPathElement(node, "dog"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementExactMatch(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "farahtek"}
|
||||||
|
test.AssertResult(t, true, parser.MatchesNextPathElement(node, "farahtek"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPathParserMatchesNextPathElementExactMismatch(t *testing.T) {
|
||||||
|
var node = NodeContext{Head: "farahtek"}
|
||||||
|
test.AssertResult(t, false, parser.MatchesNextPathElement(node, "othertek"))
|
||||||
|
}
|
||||||
|
@ -3,7 +3,6 @@ package yqlib
|
|||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
logging "gopkg.in/op/go-logging.v1"
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,20 +11,17 @@ type ValueParser interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type valueParser struct {
|
type valueParser struct {
|
||||||
log *logging.Logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewValueParser(l *logging.Logger) ValueParser {
|
func NewValueParser() ValueParser {
|
||||||
return &valueParser{log: l}
|
return &valueParser{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *valueParser) Parse(argument string, customTag string) *yaml.Node {
|
func (v *valueParser) Parse(argument string, customTag string) *yaml.Node {
|
||||||
var err interface{}
|
var err interface{}
|
||||||
var tag = customTag
|
var tag = customTag
|
||||||
|
|
||||||
var inQuotes = len(argument) > 0 && argument[0] == '"'
|
if tag == "" {
|
||||||
if tag == "" && !inQuotes {
|
|
||||||
|
|
||||||
_, err = strconv.ParseBool(argument)
|
_, err = strconv.ParseBool(argument)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tag = "!!bool"
|
tag = "!!bool"
|
||||||
@ -46,6 +42,6 @@ func (v *valueParser) Parse(argument string, customTag string) *yaml.Node {
|
|||||||
return &yaml.Node{Tag: "!!seq", Kind: yaml.SequenceNode}
|
return &yaml.Node{Tag: "!!seq", Kind: yaml.SequenceNode}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v.log.Debugf("parsed value '%v', tag: '%v'", argument, tag)
|
log.Debugf("parsed value '%v', tag: '%v'", argument, tag)
|
||||||
return &yaml.Node{Value: argument, Tag: tag, Kind: yaml.ScalarNode}
|
return &yaml.Node{Value: argument, Tag: tag, Kind: yaml.ScalarNode}
|
||||||
}
|
}
|
||||||
|
@ -4,22 +4,35 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mikefarah/yq/v3/test"
|
"github.com/mikefarah/yq/v3/test"
|
||||||
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var parseValueTests = []struct {
|
var parseValueTests = []struct {
|
||||||
argument string
|
argument string
|
||||||
expectedResult interface{}
|
customTag string
|
||||||
|
expectedTag string
|
||||||
testDescription string
|
testDescription string
|
||||||
}{
|
}{
|
||||||
{"true", true, "boolean"},
|
{"true", "", "!!bool", "boolean"},
|
||||||
{"\"true\"", "true", "boolean as string"},
|
{"true", "!!string", "!!string", "boolean forced as string"},
|
||||||
{"3.4", 3.4, "number"},
|
{"3.4", "", "!!float", "float"},
|
||||||
{"\"3.4\"", "3.4", "number as string"},
|
{"1212121", "", "!!int", "big number"},
|
||||||
{"", "", "empty string"},
|
{"1212121.1", "", "!!float", "big float number"},
|
||||||
|
{"3", "", "!!int", "int"},
|
||||||
|
{"null", "", "!!null", "null"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseValue(t *testing.T) {
|
func TestValueParserParse(t *testing.T) {
|
||||||
for _, tt := range parseValueTests {
|
for _, tt := range parseValueTests {
|
||||||
test.AssertResultWithContext(t, tt.expectedResult, NewValueParser().ParseValue(tt.argument), tt.testDescription)
|
actual := NewValueParser().Parse(tt.argument, tt.customTag)
|
||||||
|
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("[]", "")
|
||||||
|
test.AssertResult(t, "!!seq", actual.Tag)
|
||||||
|
test.AssertResult(t, yaml.SequenceNode, actual.Kind)
|
||||||
|
}
|
||||||
|
@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
go test -coverprofile=coverage.out ./...
|
go test -coverprofile=coverage.out -v $(go list ./... | grep -v -E 'examples' | grep -v -E 'test')
|
||||||
go tool cover -html=coverage.out -o cover/coverage.html
|
go tool cover -html=coverage.out -o coverage.html
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
go test -v $(go list ./... | grep -v -E 'examples')
|
go test -v $(go list ./... | grep -v -E 'examples' | grep -v -E 'test')
|
||||||
|
5
yq.go
5
yq.go
@ -30,8 +30,8 @@ var verbose = false
|
|||||||
var version = false
|
var version = false
|
||||||
var docIndex = "0"
|
var docIndex = "0"
|
||||||
var log = logging.MustGetLogger("yq")
|
var log = logging.MustGetLogger("yq")
|
||||||
var lib = yqlib.NewYqLib(log)
|
var lib = yqlib.NewYqLib()
|
||||||
var valueParser = yqlib.NewValueParser(log)
|
var valueParser = yqlib.NewValueParser()
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd := newCommandCLI()
|
cmd := newCommandCLI()
|
||||||
@ -210,6 +210,7 @@ Note that you can give a create script to perform more sophisticated yaml. This
|
|||||||
RunE: newProperty,
|
RunE: newProperty,
|
||||||
}
|
}
|
||||||
cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml")
|
cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml")
|
||||||
|
cmdNew.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)")
|
||||||
return cmdNew
|
return cmdNew
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user