| package toml | 
 |  | 
 | import ( | 
 | 	"fmt" | 
 | 	"io/ioutil" | 
 | 	"sort" | 
 | 	"strings" | 
 | 	"testing" | 
 | 	"time" | 
 | ) | 
 |  | 
 | type queryTestNode struct { | 
 | 	value    interface{} | 
 | 	position Position | 
 | } | 
 |  | 
 | func valueString(root interface{}) string { | 
 | 	result := "" //fmt.Sprintf("%T:", root) | 
 | 	switch node := root.(type) { | 
 | 	case *tomlValue: | 
 | 		return valueString(node.value) | 
 | 	case *QueryResult: | 
 | 		items := []string{} | 
 | 		for i, v := range node.Values() { | 
 | 			items = append(items, fmt.Sprintf("%s:%s", | 
 | 				node.Positions()[i].String(), valueString(v))) | 
 | 		} | 
 | 		sort.Strings(items) | 
 | 		result = "[" + strings.Join(items, ", ") + "]" | 
 | 	case queryTestNode: | 
 | 		result = fmt.Sprintf("%s:%s", | 
 | 			node.position.String(), valueString(node.value)) | 
 | 	case []interface{}: | 
 | 		items := []string{} | 
 | 		for _, v := range node { | 
 | 			items = append(items, valueString(v)) | 
 | 		} | 
 | 		sort.Strings(items) | 
 | 		result = "[" + strings.Join(items, ", ") + "]" | 
 | 	case *TomlTree: | 
 | 		// workaround for unreliable map key ordering | 
 | 		items := []string{} | 
 | 		for _, k := range node.Keys() { | 
 | 			v := node.GetPath([]string{k}) | 
 | 			items = append(items, k+":"+valueString(v)) | 
 | 		} | 
 | 		sort.Strings(items) | 
 | 		result = "{" + strings.Join(items, ", ") + "}" | 
 | 	case map[string]interface{}: | 
 | 		// workaround for unreliable map key ordering | 
 | 		items := []string{} | 
 | 		for k, v := range node { | 
 | 			items = append(items, k+":"+valueString(v)) | 
 | 		} | 
 | 		sort.Strings(items) | 
 | 		result = "{" + strings.Join(items, ", ") + "}" | 
 | 	case int64: | 
 | 		result += fmt.Sprintf("%d", node) | 
 | 	case string: | 
 | 		result += "'" + node + "'" | 
 | 	case float64: | 
 | 		result += fmt.Sprintf("%f", node) | 
 | 	case bool: | 
 | 		result += fmt.Sprintf("%t", node) | 
 | 	case time.Time: | 
 | 		result += fmt.Sprintf("'%v'", node) | 
 | 	} | 
 | 	return result | 
 | } | 
 |  | 
 | func assertValue(t *testing.T, result, ref interface{}) { | 
 | 	pathStr := valueString(result) | 
 | 	refStr := valueString(ref) | 
 | 	if pathStr != refStr { | 
 | 		t.Errorf("values do not match") | 
 | 		t.Log("test:", pathStr) | 
 | 		t.Log("ref: ", refStr) | 
 | 	} | 
 | } | 
 |  | 
 | func assertQueryPositions(t *testing.T, toml, query string, ref []interface{}) { | 
 | 	tree, err := Load(toml) | 
 | 	if err != nil { | 
 | 		t.Errorf("Non-nil toml parse error: %v", err) | 
 | 		return | 
 | 	} | 
 | 	q, err := CompileQuery(query) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 		return | 
 | 	} | 
 | 	results := q.Execute(tree) | 
 | 	assertValue(t, results, ref) | 
 | } | 
 |  | 
 | func TestQueryRoot(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"a = 42", | 
 | 		"$", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(42), | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQueryKey(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo]\na = 42", | 
 | 		"$.foo.a", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				int64(42), Position{2, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQueryKeyString(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo]\na = 42", | 
 | 		"$.foo['a']", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				int64(42), Position{2, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQueryIndex(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo]\na = [1,2,3,4,5,6,7,8,9,0]", | 
 | 		"$.foo.a[5]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				int64(6), Position{2, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQuerySliceRange(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo]\na = [1,2,3,4,5,6,7,8,9,0]", | 
 | 		"$.foo.a[0:5]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				int64(1), Position{2, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(2), Position{2, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(3), Position{2, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(4), Position{2, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(5), Position{2, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQuerySliceStep(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo]\na = [1,2,3,4,5,6,7,8,9,0]", | 
 | 		"$.foo.a[0:5:2]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				int64(1), Position{2, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(3), Position{2, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(5), Position{2, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQueryAny(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo.bar]\na=1\nb=2\n[foo.baz]\na=3\nb=4", | 
 | 		"$.foo.*", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(1), | 
 | 					"b": int64(2), | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(3), | 
 | 					"b": int64(4), | 
 | 				}, Position{4, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 | func TestQueryUnionSimple(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", | 
 | 		"$.*[bar,foo]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(1), | 
 | 					"b": int64(2), | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(3), | 
 | 					"b": int64(4), | 
 | 				}, Position{4, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(5), | 
 | 					"b": int64(6), | 
 | 				}, Position{7, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQueryRecursionAll(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", | 
 | 		"$..*", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"foo": map[string]interface{}{ | 
 | 						"bar": map[string]interface{}{ | 
 | 							"a": int64(1), | 
 | 							"b": int64(2), | 
 | 						}, | 
 | 					}, | 
 | 					"baz": map[string]interface{}{ | 
 | 						"foo": map[string]interface{}{ | 
 | 							"a": int64(3), | 
 | 							"b": int64(4), | 
 | 						}, | 
 | 					}, | 
 | 					"gorf": map[string]interface{}{ | 
 | 						"foo": map[string]interface{}{ | 
 | 							"a": int64(5), | 
 | 							"b": int64(6), | 
 | 						}, | 
 | 					}, | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"bar": map[string]interface{}{ | 
 | 						"a": int64(1), | 
 | 						"b": int64(2), | 
 | 					}, | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(1), | 
 | 					"b": int64(2), | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(1), Position{2, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(2), Position{3, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"foo": map[string]interface{}{ | 
 | 						"a": int64(3), | 
 | 						"b": int64(4), | 
 | 					}, | 
 | 				}, Position{4, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(3), | 
 | 					"b": int64(4), | 
 | 				}, Position{4, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(3), Position{5, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(4), Position{6, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"foo": map[string]interface{}{ | 
 | 						"a": int64(5), | 
 | 						"b": int64(6), | 
 | 					}, | 
 | 				}, Position{7, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(5), | 
 | 					"b": int64(6), | 
 | 				}, Position{7, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(5), Position{8, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(6), Position{9, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQueryRecursionUnionSimple(t *testing.T) { | 
 | 	assertQueryPositions(t, | 
 | 		"[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", | 
 | 		"$..['foo','bar']", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"bar": map[string]interface{}{ | 
 | 						"a": int64(1), | 
 | 						"b": int64(2), | 
 | 					}, | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(3), | 
 | 					"b": int64(4), | 
 | 				}, Position{4, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(1), | 
 | 					"b": int64(2), | 
 | 				}, Position{1, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"a": int64(5), | 
 | 					"b": int64(6), | 
 | 				}, Position{7, 1}, | 
 | 			}, | 
 | 		}) | 
 | } | 
 |  | 
 | func TestQueryFilterFn(t *testing.T) { | 
 | 	buff, err := ioutil.ReadFile("example.toml") | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 		return | 
 | 	} | 
 |  | 
 | 	assertQueryPositions(t, string(buff), | 
 | 		"$..[?(int)]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				int64(8001), Position{13, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(8001), Position{13, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(8002), Position{13, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				int64(5000), Position{14, 1}, | 
 | 			}, | 
 | 		}) | 
 |  | 
 | 	assertQueryPositions(t, string(buff), | 
 | 		"$..[?(string)]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				"TOML Example", Position{3, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"Tom Preston-Werner", Position{6, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"GitHub", Position{7, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"GitHub Cofounder & CEO\nLikes tater tots and beer.", | 
 | 				Position{8, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"192.168.1.1", Position{12, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"10.0.0.1", Position{21, 3}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"eqdc10", Position{22, 3}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"10.0.0.2", Position{25, 3}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				"eqdc10", Position{26, 3}, | 
 | 			}, | 
 | 		}) | 
 |  | 
 | 	assertQueryPositions(t, string(buff), | 
 | 		"$..[?(float)]", | 
 | 		[]interface{}{ | 
 | 		// no float values in document | 
 | 		}) | 
 |  | 
 | 	tv, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") | 
 | 	assertQueryPositions(t, string(buff), | 
 | 		"$..[?(tree)]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"name":         "Tom Preston-Werner", | 
 | 					"organization": "GitHub", | 
 | 					"bio":          "GitHub Cofounder & CEO\nLikes tater tots and beer.", | 
 | 					"dob":          tv, | 
 | 				}, Position{5, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"server":         "192.168.1.1", | 
 | 					"ports":          []interface{}{int64(8001), int64(8001), int64(8002)}, | 
 | 					"connection_max": int64(5000), | 
 | 					"enabled":        true, | 
 | 				}, Position{11, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"alpha": map[string]interface{}{ | 
 | 						"ip": "10.0.0.1", | 
 | 						"dc": "eqdc10", | 
 | 					}, | 
 | 					"beta": map[string]interface{}{ | 
 | 						"ip": "10.0.0.2", | 
 | 						"dc": "eqdc10", | 
 | 					}, | 
 | 				}, Position{17, 1}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"ip": "10.0.0.1", | 
 | 					"dc": "eqdc10", | 
 | 				}, Position{20, 3}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"ip": "10.0.0.2", | 
 | 					"dc": "eqdc10", | 
 | 				}, Position{24, 3}, | 
 | 			}, | 
 | 			queryTestNode{ | 
 | 				map[string]interface{}{ | 
 | 					"data": []interface{}{ | 
 | 						[]interface{}{"gamma", "delta"}, | 
 | 						[]interface{}{int64(1), int64(2)}, | 
 | 					}, | 
 | 				}, Position{28, 1}, | 
 | 			}, | 
 | 		}) | 
 |  | 
 | 	assertQueryPositions(t, string(buff), | 
 | 		"$..[?(time)]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				tv, Position{9, 1}, | 
 | 			}, | 
 | 		}) | 
 |  | 
 | 	assertQueryPositions(t, string(buff), | 
 | 		"$..[?(bool)]", | 
 | 		[]interface{}{ | 
 | 			queryTestNode{ | 
 | 				true, Position{15, 1}, | 
 | 			}, | 
 | 		}) | 
 | } |