mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			223 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2015 The Kubernetes Authors All rights reserved.
 | 
						|
 | 
						|
Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
you may not use this file except in compliance with the License.
 | 
						|
You may obtain a copy of the License at
 | 
						|
 | 
						|
    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 | 
						|
Unless required by applicable law or agreed to in writing, software
 | 
						|
distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
See the License for the specific language governing permissions and
 | 
						|
limitations under the License.
 | 
						|
*/
 | 
						|
 | 
						|
package jsonpath
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
type jsonpathTest struct {
 | 
						|
	name     string
 | 
						|
	template string
 | 
						|
	input    interface{}
 | 
						|
	expect   string
 | 
						|
}
 | 
						|
 | 
						|
func testJSONPath(tests []jsonpathTest, t *testing.T) {
 | 
						|
	for _, test := range tests {
 | 
						|
		j := New(test.name)
 | 
						|
		err := j.Parse(test.template)
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("in %s, parse %s error %v", test.name, test.template, err)
 | 
						|
		}
 | 
						|
		buf := new(bytes.Buffer)
 | 
						|
		err = j.Execute(buf, test.input)
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("in %s, execute error %v", test.name, err)
 | 
						|
		}
 | 
						|
		out := buf.String()
 | 
						|
		if out != test.expect {
 | 
						|
			t.Errorf(`in %s, expect to get "%s", got "%s"`, test.name, test.expect, out)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testFailJSONPath(tests []jsonpathTest, t *testing.T) {
 | 
						|
	for _, test := range tests {
 | 
						|
		j := New(test.name)
 | 
						|
		err := j.Parse(test.template)
 | 
						|
		if err != nil {
 | 
						|
			t.Errorf("in %s, parse %s error %v", test.name, test.template, err)
 | 
						|
		}
 | 
						|
		buf := new(bytes.Buffer)
 | 
						|
		err = j.Execute(buf, test.input)
 | 
						|
		var out string
 | 
						|
		if err == nil {
 | 
						|
			out = "nil"
 | 
						|
		} else {
 | 
						|
			out = err.Error()
 | 
						|
		}
 | 
						|
		if out != test.expect {
 | 
						|
			t.Errorf("in %s, expect to get error %s, got %s", test.name, test.expect, out)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type book struct {
 | 
						|
	Category string
 | 
						|
	Author   string
 | 
						|
	Title    string
 | 
						|
	Price    float32
 | 
						|
}
 | 
						|
 | 
						|
func (b book) String() string {
 | 
						|
	return fmt.Sprintf("{Category: %s, Author: %s, Title: %s, Price: %v}", b.Category, b.Author, b.Title, b.Price)
 | 
						|
}
 | 
						|
 | 
						|
type bicycle struct {
 | 
						|
	Color string
 | 
						|
	Price float32
 | 
						|
}
 | 
						|
 | 
						|
type store struct {
 | 
						|
	Book    []book
 | 
						|
	Bicycle bicycle
 | 
						|
	Name    string
 | 
						|
	Labels  map[string]int
 | 
						|
}
 | 
						|
 | 
						|
func TestStructInput(t *testing.T) {
 | 
						|
 | 
						|
	storeData := store{
 | 
						|
		Name: "jsonpath",
 | 
						|
		Book: []book{
 | 
						|
			{"reference", "Nigel Rees", "Sayings of the Centurey", 8.95},
 | 
						|
			{"fiction", "Evelyn Waugh", "Sword of Honour", 12.99},
 | 
						|
			{"fiction", "Herman Melville", "Moby Dick", 8.99},
 | 
						|
		},
 | 
						|
		Bicycle: bicycle{"red", 19.95},
 | 
						|
		Labels: map[string]int{
 | 
						|
			"engieer":  10,
 | 
						|
			"web/html": 15,
 | 
						|
			"k8s-app":  20,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	storeTests := []jsonpathTest{
 | 
						|
		{"plain", "hello jsonpath", nil, "hello jsonpath"},
 | 
						|
		{"recursive", "{..}", []int{1, 2, 3}, "[1 2 3]"},
 | 
						|
		{"filter", "{[?(@<5)]}", []int{2, 6, 3, 7}, "2 3"},
 | 
						|
		{"quote", `{"{"}`, nil, "{"},
 | 
						|
		{"union", "{[1,3,4]}", []int{0, 1, 2, 3, 4}, "1 3 4"},
 | 
						|
		{"array", "{[0:2]}", []string{"Monday", "Tudesday"}, "Monday Tudesday"},
 | 
						|
		{"variable", "hello {.Name}", storeData, "hello jsonpath"},
 | 
						|
		{"dict/", "{$.Labels.web/html}", storeData, "15"},
 | 
						|
		{"dict-", "{.Labels.k8s-app}", storeData, "20"},
 | 
						|
		{"nest", "{.Bicycle.Color}", storeData, "red"},
 | 
						|
		{"allarray", "{.Book[*].Author}", storeData, "Nigel Rees Evelyn Waugh Herman Melville"},
 | 
						|
		{"allfileds", "{.Bicycle.*}", storeData, "red 19.95"},
 | 
						|
		{"recurfileds", "{..Price}", storeData, "8.95 12.99 8.99 19.95"},
 | 
						|
		{"lastarray", "{.Book[-1:]}", storeData,
 | 
						|
			"{Category: fiction, Author: Herman Melville, Title: Moby Dick, Price: 8.99}"},
 | 
						|
		{"recurarray", "{..Book[2]}", storeData,
 | 
						|
			"{Category: fiction, Author: Herman Melville, Title: Moby Dick, Price: 8.99}"},
 | 
						|
	}
 | 
						|
	testJSONPath(storeTests, t)
 | 
						|
 | 
						|
	failStoreTests := []jsonpathTest{
 | 
						|
		{"invalid identfier", "{hello}", storeData, "unrecongnized identifier hello"},
 | 
						|
		{"nonexistent field", "{.hello}", storeData, "hello is not found"},
 | 
						|
		{"invalid array", "{.Labels[0]}", storeData, "<map[string]int Value> is not array or slice"},
 | 
						|
		{"invalid filter operator", "{.Book[?(@.Price<>10)]}", storeData, "unrecognized filter operator <>"},
 | 
						|
		{"redundent end", "{range .Labels.*}{@}{end}{end}", storeData, "not in range, nothing to end"},
 | 
						|
	}
 | 
						|
	testFailJSONPath(failStoreTests, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestJSONInput(t *testing.T) {
 | 
						|
	var pointsJSON = []byte(`[
 | 
						|
		{"id": "i1", "x":4, "y":-5},
 | 
						|
		{"id": "i2", "x":-2, "y":-5, "z":1},
 | 
						|
		{"id": "i3", "x":  8, "y":  3 },
 | 
						|
		{"id": "i4", "x": -6, "y": -1 },
 | 
						|
		{"id": "i5", "x":  0, "y":  2, "z": 1 },
 | 
						|
		{"id": "i6", "x":  1, "y":  4 }
 | 
						|
	]`)
 | 
						|
	var pointsData interface{}
 | 
						|
	err := json.Unmarshal(pointsJSON, &pointsData)
 | 
						|
	if err != nil {
 | 
						|
		t.Error(err)
 | 
						|
	}
 | 
						|
	pointsTests := []jsonpathTest{
 | 
						|
		{"exists filter", "{[?(@.z)].id}", pointsData, "i2 i5"},
 | 
						|
		{"bracket key", "{[0]['id']}", pointsData, "i1"},
 | 
						|
	}
 | 
						|
	testJSONPath(pointsTests, t)
 | 
						|
}
 | 
						|
 | 
						|
// TestKubenates tests some use cases from kubenates
 | 
						|
func TestKubenates(t *testing.T) {
 | 
						|
	var input = []byte(`{
 | 
						|
	  "kind": "List",
 | 
						|
	  "items":[
 | 
						|
		{
 | 
						|
		  "kind":"None",
 | 
						|
		  "metadata":{"name":"127.0.0.1"},
 | 
						|
		  "status":{
 | 
						|
			"capacity":{"cpu":"4"},
 | 
						|
			"addresses":[{"type": "LegacyHostIP", "address":"127.0.0.1"}]
 | 
						|
		  }
 | 
						|
		},
 | 
						|
		{
 | 
						|
		  "kind":"None",
 | 
						|
		  "metadata":{"name":"127.0.0.2"},
 | 
						|
		  "status":{
 | 
						|
			"capacity":{"cpu":"8"},
 | 
						|
			"addresses":[
 | 
						|
			  {"type": "LegacyHostIP", "address":"127.0.0.2"},
 | 
						|
			  {"type": "another", "address":"127.0.0.3"}
 | 
						|
			]
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	  ],
 | 
						|
	  "users":[
 | 
						|
	    {
 | 
						|
	      "name": "myself",
 | 
						|
	      "user": {}
 | 
						|
	    },
 | 
						|
	    {
 | 
						|
	      "name": "e2e",
 | 
						|
	      "user": {"username": "admin", "password": "secret"}
 | 
						|
	  	}
 | 
						|
	  ]
 | 
						|
	}`)
 | 
						|
	var nodesData interface{}
 | 
						|
	err := json.Unmarshal(input, &nodesData)
 | 
						|
	if err != nil {
 | 
						|
		t.Error(err)
 | 
						|
	}
 | 
						|
 | 
						|
	nodesTests := []jsonpathTest{
 | 
						|
		{"range item", "{range .items[*]}{.metadata.name}, {end}{.kind}", nodesData, `127.0.0.1, 127.0.0.2, List`},
 | 
						|
		{"range addresss", "{.items[*].status.addresses[*].address}", nodesData,
 | 
						|
			`127.0.0.1 127.0.0.2 127.0.0.3`},
 | 
						|
		{"double range", "{range .items[*]}{range .status.addresses[*]}{.address}, {end}{end}", nodesData,
 | 
						|
			`127.0.0.1, 127.0.0.2, 127.0.0.3, `},
 | 
						|
		{"recursive name", "{..name}", nodesData, `127.0.0.1 127.0.0.2 myself e2e`},
 | 
						|
		{"item name", "{.items[*].metadata.name}", nodesData, `127.0.0.1 127.0.0.2`},
 | 
						|
		{"union nodes capacity", "{.items[*]['metadata.name', 'status.capacity']}", nodesData,
 | 
						|
			`127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]`},
 | 
						|
		{"range nodes capacity", "{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}", nodesData,
 | 
						|
			`[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] `},
 | 
						|
		{"user password", `{.users[?(@.name=="e2e")].user.password}`, &nodesData, "secret"},
 | 
						|
	}
 | 
						|
	testJSONPath(nodesTests, t)
 | 
						|
}
 |