| // Copyright 2018, OpenCensus Authors |
| // |
| // 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 tracestate |
| |
| import ( |
| "fmt" |
| "testing" |
| ) |
| |
| func checkFront(t *testing.T, tracestate *Tracestate, wantKey, testname string) { |
| gotKey := tracestate.entries[0].Key |
| if gotKey != wantKey { |
| t.Errorf("test:%s: first entry in the list: got %q want %q", testname, gotKey, wantKey) |
| } |
| } |
| |
| func checkBack(t *testing.T, tracestate *Tracestate, wantKey, testname string) { |
| gotKey := tracestate.entries[len(tracestate.entries)-1].Key |
| if gotKey != wantKey { |
| t.Errorf("test:%s: last entry in the list: got %q want %q", testname, gotKey, wantKey) |
| } |
| } |
| |
| func checkSize(t *testing.T, tracestate *Tracestate, wantSize int, testname string) { |
| if gotSize := len(tracestate.entries); gotSize != wantSize { |
| t.Errorf("test:%s: size of the list: got %q want %q", testname, gotSize, wantSize) |
| } |
| } |
| |
| func (ts *Tracestate) get(key string) (string, bool) { |
| if ts == nil { |
| return "", false |
| } |
| for _, entry := range ts.entries { |
| if entry.Key == key { |
| return entry.Value, true |
| } |
| } |
| return "", false |
| } |
| |
| func checkKeyValue(t *testing.T, tracestate *Tracestate, key, wantValue, testname string) { |
| wantOk := true |
| if wantValue == "" { |
| wantOk = false |
| } |
| gotValue, gotOk := tracestate.get(key) |
| if wantOk != gotOk || gotValue != wantValue { |
| t.Errorf("test:%s: get value for key=%s failed: got %q want %q", testname, key, gotValue, wantValue) |
| } |
| } |
| |
| func checkError(t *testing.T, tracestate *Tracestate, err error, testname, msg string) { |
| if err != nil { |
| t.Errorf("test:%s: %s: tracestate=%v, error= %v", testname, msg, tracestate, err) |
| } |
| } |
| |
| func wantError(t *testing.T, tracestate *Tracestate, err error, testname, msg string) { |
| if err == nil { |
| t.Errorf("test:%s: %s: tracestate=%v, error=%v", testname, msg, tracestate, err) |
| } |
| } |
| |
| func TestCreateWithNullParent(t *testing.T) { |
| key1, value1 := "hello", "world" |
| testname := "TestCreateWithNullParent" |
| |
| entry := Entry{key1, value1} |
| tracestate, err := New(nil, entry) |
| checkError(t, tracestate, err, testname, "create failed from null parent") |
| checkKeyValue(t, tracestate, key1, value1, testname) |
| } |
| |
| func TestCreateFromParentWithSingleKey(t *testing.T) { |
| key1, value1, key2, value2 := "hello", "world", "foo", "bar" |
| testname := "TestCreateFromParentWithSingleKey" |
| |
| entry1 := Entry{key1, value1} |
| entry2 := Entry{key2, value2} |
| parent, _ := New(nil, entry1) |
| tracestate, err := New(parent, entry2) |
| |
| checkError(t, tracestate, err, testname, "create failed from parent with single key") |
| checkKeyValue(t, tracestate, key2, value2, testname) |
| checkFront(t, tracestate, key2, testname) |
| checkBack(t, tracestate, key1, testname) |
| } |
| |
| func TestCreateFromParentWithDoubleKeys(t *testing.T) { |
| key1, value1, key2, value2, key3, value3 := "hello", "world", "foo", "bar", "bar", "baz" |
| testname := "TestCreateFromParentWithDoubleKeys" |
| |
| entry1 := Entry{key1, value1} |
| entry2 := Entry{key2, value2} |
| entry3 := Entry{key3, value3} |
| parent, _ := New(nil, entry2, entry1) |
| tracestate, err := New(parent, entry3) |
| |
| checkError(t, tracestate, err, testname, "create failed from parent with double keys") |
| checkKeyValue(t, tracestate, key3, value3, testname) |
| checkFront(t, tracestate, key3, testname) |
| checkBack(t, tracestate, key1, testname) |
| } |
| |
| func TestCreateFromParentWithExistingKey(t *testing.T) { |
| key1, value1, key2, value2, key3, value3 := "hello", "world", "foo", "bar", "hello", "baz" |
| testname := "TestCreateFromParentWithExistingKey" |
| |
| entry1 := Entry{key1, value1} |
| entry2 := Entry{key2, value2} |
| entry3 := Entry{key3, value3} |
| parent, _ := New(nil, entry2, entry1) |
| tracestate, err := New(parent, entry3) |
| |
| checkError(t, tracestate, err, testname, "create failed with an existing key") |
| checkKeyValue(t, tracestate, key3, value3, testname) |
| checkFront(t, tracestate, key3, testname) |
| checkBack(t, tracestate, key2, testname) |
| checkSize(t, tracestate, 2, testname) |
| } |
| |
| func TestImplicitImmutableTracestate(t *testing.T) { |
| key1, value1, key2, value2, key3, value3 := "hello", "world", "hello", "bar", "foo", "baz" |
| testname := "TestImplicitImmutableTracestate" |
| |
| entry1 := Entry{key1, value1} |
| entry2 := Entry{key2, value2} |
| parent, _ := New(nil, entry1) |
| tracestate, err := New(parent, entry2) |
| |
| checkError(t, tracestate, err, testname, "create failed") |
| checkKeyValue(t, tracestate, key2, value2, testname) |
| checkKeyValue(t, parent, key2, value1, testname) |
| |
| // Get and update entries. |
| entries := tracestate.Entries() |
| entry := Entry{key3, value3} |
| entries = append(entries, entry) |
| |
| // Check Tracestate does not have key3. |
| checkKeyValue(t, tracestate, key3, "", testname) |
| // Check that we added the key3 in the entries |
| tracestate, err = New(nil, entries...) |
| checkError(t, tracestate, err, testname, "create failed") |
| checkKeyValue(t, tracestate, key3, value3, testname) |
| } |
| |
| func TestKeyWithValidChar(t *testing.T) { |
| testname := "TestKeyWithValidChar" |
| |
| arrayRune := []rune("") |
| for c := 'a'; c <= 'z'; c++ { |
| arrayRune = append(arrayRune, c) |
| } |
| for c := '0'; c <= '9'; c++ { |
| arrayRune = append(arrayRune, c) |
| } |
| arrayRune = append(arrayRune, '_') |
| arrayRune = append(arrayRune, '-') |
| arrayRune = append(arrayRune, '*') |
| arrayRune = append(arrayRune, '/') |
| key := string(arrayRune) |
| entry := Entry{key, "world"} |
| tracestate, err := New(nil, entry) |
| |
| checkError(t, tracestate, err, testname, "create failed when the key contains all valid characters") |
| } |
| |
| func TestKeyWithInvalidChar(t *testing.T) { |
| testname := "TestKeyWithInvalidChar" |
| |
| keys := []string{"1ab", "1ab2", "Abc", " abc", "a=b"} |
| |
| for _, key := range keys { |
| entry := Entry{key, "world"} |
| tracestate, err := New(nil, entry) |
| wantError(t, tracestate, err, testname, fmt.Sprintf( |
| "create did not err with invalid key=%q", key)) |
| } |
| } |
| |
| func TestNilKey(t *testing.T) { |
| testname := "TestNilKey" |
| |
| entry := Entry{"", "world"} |
| tracestate, err := New(nil, entry) |
| wantError(t, tracestate, err, testname, "create did not err when the key is nil (\"\")") |
| } |
| |
| func TestValueWithInvalidChar(t *testing.T) { |
| testname := "TestValueWithInvalidChar" |
| |
| keys := []string{"A=B", "A,B", "AB "} |
| |
| for _, value := range keys { |
| entry := Entry{"hello", value} |
| tracestate, err := New(nil, entry) |
| wantError(t, tracestate, err, testname, |
| fmt.Sprintf("create did not err when the value is invalid (%q)", value)) |
| } |
| } |
| |
| func TestNilValue(t *testing.T) { |
| testname := "TestNilValue" |
| |
| tracestate, err := New(nil, Entry{"hello", ""}) |
| wantError(t, tracestate, err, testname, "create did not err when the value is nil (\"\")") |
| } |
| |
| func TestInvalidKeyLen(t *testing.T) { |
| testname := "TestInvalidKeyLen" |
| |
| arrayRune := []rune("") |
| for i := 0; i <= keyMaxSize+1; i++ { |
| arrayRune = append(arrayRune, 'a') |
| } |
| key := string(arrayRune) |
| tracestate, err := New(nil, Entry{key, "world"}) |
| |
| wantError(t, tracestate, err, testname, |
| fmt.Sprintf("create did not err when the length (%d) of the key is larger than max (%d)", |
| len(key), keyMaxSize)) |
| } |
| |
| func TestInvalidValueLen(t *testing.T) { |
| testname := "TestInvalidValueLen" |
| |
| arrayRune := []rune("") |
| for i := 0; i <= valueMaxSize+1; i++ { |
| arrayRune = append(arrayRune, 'a') |
| } |
| value := string(arrayRune) |
| tracestate, err := New(nil, Entry{"hello", value}) |
| |
| wantError(t, tracestate, err, testname, |
| fmt.Sprintf("create did not err when the length (%d) of the value is larger than max (%d)", |
| len(value), valueMaxSize)) |
| } |
| |
| func TestCreateFromArrayWithOverLimitKVPairs(t *testing.T) { |
| testname := "TestCreateFromArrayWithOverLimitKVPairs" |
| |
| entries := []Entry{} |
| for i := 0; i <= maxKeyValuePairs; i++ { |
| key := fmt.Sprintf("a%db", i) |
| entry := Entry{key, "world"} |
| entries = append(entries, entry) |
| } |
| tracestate, err := New(nil, entries...) |
| wantError(t, tracestate, err, testname, |
| fmt.Sprintf("create did not err when the number (%d) of key-value pairs is larger than max (%d)", |
| len(entries), maxKeyValuePairs)) |
| } |
| |
| func TestCreateFromEmptyArray(t *testing.T) { |
| testname := "TestCreateFromEmptyArray" |
| |
| tracestate, err := New(nil, nil...) |
| checkError(t, tracestate, err, testname, |
| "failed to create nil tracestate") |
| } |
| |
| func TestCreateFromParentWithOverLimitKVPairs(t *testing.T) { |
| testname := "TestCreateFromParentWithOverLimitKVPairs" |
| |
| entries := []Entry{} |
| for i := 0; i < maxKeyValuePairs; i++ { |
| key := fmt.Sprintf("a%db", i) |
| entry := Entry{key, "world"} |
| entries = append(entries, entry) |
| } |
| parent, err := New(nil, entries...) |
| |
| checkError(t, parent, err, testname, fmt.Sprintf("create failed to add %d key-value pair", maxKeyValuePairs)) |
| |
| // Add one more to go over the limit |
| key := fmt.Sprintf("a%d", maxKeyValuePairs) |
| tracestate, err := New(parent, Entry{key, "world"}) |
| wantError(t, tracestate, err, testname, |
| fmt.Sprintf("create did not err when attempted to exceed the key-value pair limit of %d", maxKeyValuePairs)) |
| } |
| |
| func TestCreateFromArrayWithDuplicateKeys(t *testing.T) { |
| key1, value1, key2, value2, key3, value3 := "hello", "world", "foo", "bar", "hello", "baz" |
| testname := "TestCreateFromArrayWithDuplicateKeys" |
| |
| entry1 := Entry{key1, value1} |
| entry2 := Entry{key2, value2} |
| entry3 := Entry{key3, value3} |
| tracestate, err := New(nil, entry1, entry2, entry3) |
| |
| wantError(t, tracestate, err, testname, |
| "create did not err when entries contained duplicate keys") |
| } |
| |
| func TestEntriesWithNil(t *testing.T) { |
| ts, err := New(nil) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if got, want := len(ts.Entries()), 0; got != want { |
| t.Errorf("zero value should have no entries, got %v; want %v", got, want) |
| } |
| } |