| // Copyright 2017, 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 tag |
| |
| import ( |
| "context" |
| "fmt" |
| "reflect" |
| "strings" |
| "testing" |
| ) |
| |
| var ( |
| ttlUnlimitedPropMd = createMetadatas(WithTTL(TTLUnlimitedPropagation)) |
| ttlNoPropMd = createMetadatas(WithTTL(TTLNoPropagation)) |
| ) |
| |
| func TestContext(t *testing.T) { |
| k1, _ := NewKey("k1") |
| k2, _ := NewKey("k2") |
| |
| ctx := context.Background() |
| ctx, _ = New(ctx, |
| Insert(k1, "v1"), |
| Insert(k2, "v2"), |
| ) |
| got := FromContext(ctx) |
| want := newMap() |
| want.insert(k1, "v1", ttlUnlimitedPropMd) |
| want.insert(k2, "v2", ttlUnlimitedPropMd) |
| |
| if !reflect.DeepEqual(got, want) { |
| t.Errorf("Map = %#v; want %#v", got, want) |
| } |
| } |
| |
| func TestDo(t *testing.T) { |
| k1, _ := NewKey("k1") |
| k2, _ := NewKey("k2") |
| ctx := context.Background() |
| ctx, _ = New(ctx, |
| Insert(k1, "v1"), |
| Insert(k2, "v2"), |
| ) |
| got := FromContext(ctx) |
| want := newMap() |
| want.insert(k1, "v1", ttlUnlimitedPropMd) |
| want.insert(k2, "v2", ttlUnlimitedPropMd) |
| Do(ctx, func(ctx context.Context) { |
| got = FromContext(ctx) |
| }) |
| if !reflect.DeepEqual(got, want) { |
| t.Errorf("Map = %#v; want %#v", got, want) |
| } |
| } |
| |
| func TestNewMap(t *testing.T) { |
| k1, _ := NewKey("k1") |
| k2, _ := NewKey("k2") |
| k3, _ := NewKey("k3") |
| k4, _ := NewKey("k4") |
| k5, _ := NewKey("k5") |
| |
| initial := makeTestTagMap(5) |
| |
| tests := []struct { |
| name string |
| initial *Map |
| mods []Mutator |
| want *Map |
| }{ |
| { |
| name: "from empty; insert", |
| initial: nil, |
| mods: []Mutator{ |
| Insert(k5, "v5"), |
| }, |
| want: makeTestTagMap(2, 4, 5), |
| }, |
| { |
| name: "from empty; insert existing", |
| initial: nil, |
| mods: []Mutator{ |
| Insert(k1, "v1"), |
| }, |
| want: makeTestTagMap(1, 2, 4), |
| }, |
| { |
| name: "from empty; update", |
| initial: nil, |
| mods: []Mutator{ |
| Update(k1, "v1"), |
| }, |
| want: makeTestTagMap(2, 4), |
| }, |
| { |
| name: "from empty; update unexisting", |
| initial: nil, |
| mods: []Mutator{ |
| Update(k5, "v5"), |
| }, |
| want: makeTestTagMap(2, 4), |
| }, |
| { |
| name: "from existing; upsert", |
| initial: initial, |
| mods: []Mutator{ |
| Upsert(k5, "v5"), |
| }, |
| want: makeTestTagMap(2, 4, 5), |
| }, |
| { |
| name: "from existing; delete", |
| initial: initial, |
| mods: []Mutator{ |
| Delete(k2), |
| }, |
| want: makeTestTagMap(4, 5), |
| }, |
| { |
| name: "from empty; invalid", |
| initial: nil, |
| mods: []Mutator{ |
| Insert(k5, "v\x19"), |
| Upsert(k5, "v\x19"), |
| Update(k5, "v\x19"), |
| }, |
| want: nil, |
| }, |
| { |
| name: "from empty; no partial", |
| initial: nil, |
| mods: []Mutator{ |
| Insert(k5, "v1"), |
| Update(k5, "v\x19"), |
| }, |
| want: nil, |
| }, |
| } |
| |
| for _, tt := range tests { |
| mods := []Mutator{ |
| Insert(k1, "v1"), |
| Insert(k2, "v2"), |
| Update(k3, "v3"), |
| Upsert(k4, "v4"), |
| Insert(k2, "v2"), |
| Delete(k1), |
| } |
| mods = append(mods, tt.mods...) |
| ctx := NewContext(context.Background(), tt.initial) |
| ctx, err := New(ctx, mods...) |
| if tt.want != nil && err != nil { |
| t.Errorf("%v: New = %v", tt.name, err) |
| } |
| |
| if got, want := FromContext(ctx), tt.want; !reflect.DeepEqual(got, want) { |
| t.Errorf("%v: got %v; want %v", tt.name, got, want) |
| } |
| } |
| } |
| |
| func TestNewMapWithMetadata(t *testing.T) { |
| k3, _ := NewKey("k3") |
| k4, _ := NewKey("k4") |
| k5, _ := NewKey("k5") |
| |
| tests := []struct { |
| name string |
| initial *Map |
| mods []Mutator |
| want *Map |
| }{ |
| { |
| name: "from empty; insert", |
| initial: nil, |
| mods: []Mutator{ |
| Insert(k5, "5", WithTTL(TTLNoPropagation)), |
| Insert(k4, "4"), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlNoPropMd}, |
| tagContent{"4", ttlUnlimitedPropMd}), |
| }, |
| { |
| name: "from existing; insert existing", |
| initial: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}), |
| mods: []Mutator{ |
| Insert(k5, "5", WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}), |
| }, |
| { |
| name: "from existing; update non-existing", |
| initial: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}), |
| mods: []Mutator{ |
| Update(k4, "4", WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: makeTestTagMapWithMetadata(tagContent{"5", ttlNoPropMd}), |
| }, |
| { |
| name: "from existing; update existing", |
| initial: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlUnlimitedPropMd}, |
| tagContent{"4", ttlNoPropMd}), |
| mods: []Mutator{ |
| Update(k5, "5"), |
| Update(k4, "4", WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlUnlimitedPropMd}, |
| tagContent{"4", ttlUnlimitedPropMd}), |
| }, |
| { |
| name: "from existing; upsert existing", |
| initial: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlNoPropMd}, |
| tagContent{"4", ttlNoPropMd}), |
| mods: []Mutator{ |
| Upsert(k4, "4", WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlNoPropMd}, |
| tagContent{"4", ttlUnlimitedPropMd}), |
| }, |
| { |
| name: "from existing; upsert non-existing", |
| initial: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlNoPropMd}), |
| mods: []Mutator{ |
| Upsert(k4, "4", WithTTL(TTLUnlimitedPropagation)), |
| Upsert(k3, "3"), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlNoPropMd}, |
| tagContent{"4", ttlUnlimitedPropMd}, |
| tagContent{"3", ttlUnlimitedPropMd}), |
| }, |
| { |
| name: "from existing; delete", |
| initial: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlNoPropMd}, |
| tagContent{"4", ttlNoPropMd}), |
| mods: []Mutator{ |
| Delete(k5), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"4", ttlNoPropMd}), |
| }, |
| { |
| name: "from non-existing; upsert with multiple-metadata", |
| initial: nil, |
| mods: []Mutator{ |
| Upsert(k4, "4", WithTTL(TTLUnlimitedPropagation), WithTTL(TTLNoPropagation)), |
| Upsert(k5, "5", WithTTL(TTLNoPropagation), WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"4", ttlNoPropMd}, |
| tagContent{"5", ttlUnlimitedPropMd}), |
| }, |
| { |
| name: "from non-existing; insert with multiple-metadata", |
| initial: nil, |
| mods: []Mutator{ |
| Insert(k5, "5", WithTTL(TTLNoPropagation), WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlUnlimitedPropMd}), |
| }, |
| { |
| name: "from existing; update with multiple-metadata", |
| initial: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlNoPropMd}), |
| mods: []Mutator{ |
| Update(k5, "5", WithTTL(TTLNoPropagation), WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: makeTestTagMapWithMetadata( |
| tagContent{"5", ttlUnlimitedPropMd}), |
| }, |
| { |
| name: "from empty; update invalid", |
| initial: nil, |
| mods: []Mutator{ |
| Insert(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)), |
| Upsert(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)), |
| Update(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: nil, |
| }, |
| { |
| name: "from empty; insert partial", |
| initial: nil, |
| mods: []Mutator{ |
| Upsert(k3, "3", WithTTL(TTLUnlimitedPropagation)), |
| Upsert(k4, "4\x19", WithTTL(TTLUnlimitedPropagation)), |
| }, |
| want: nil, |
| }, |
| } |
| |
| // Test api for insert, update, and upsert using metadata. |
| for _, tt := range tests { |
| ctx := NewContext(context.Background(), tt.initial) |
| ctx, err := New(ctx, tt.mods...) |
| if tt.want != nil && err != nil { |
| t.Errorf("%v: New = %v", tt.name, err) |
| } |
| |
| if got, want := FromContext(ctx), tt.want; !reflect.DeepEqual(got, want) { |
| t.Errorf("%v: got %v; want %v", tt.name, got, want) |
| } |
| } |
| } |
| |
| func TestNewValidation(t *testing.T) { |
| tests := []struct { |
| err string |
| seed *Map |
| }{ |
| // Key name validation in seed |
| {err: "invalid key", seed: &Map{m: map[Key]tagContent{{name: ""}: {"foo", ttlNoPropMd}}}}, |
| {err: "", seed: &Map{m: map[Key]tagContent{{name: "key"}: {"foo", ttlNoPropMd}}}}, |
| {err: "", seed: &Map{m: map[Key]tagContent{{name: strings.Repeat("a", 255)}: {"census", ttlNoPropMd}}}}, |
| {err: "invalid key", seed: &Map{m: map[Key]tagContent{{name: strings.Repeat("a", 256)}: {"census", ttlNoPropMd}}}}, |
| {err: "invalid key", seed: &Map{m: map[Key]tagContent{{name: "Приве́т"}: {"census", ttlNoPropMd}}}}, |
| |
| // Value validation |
| {err: "", seed: &Map{m: map[Key]tagContent{{name: "key"}: {"", ttlNoPropMd}}}}, |
| {err: "", seed: &Map{m: map[Key]tagContent{{name: "key"}: {strings.Repeat("a", 255), ttlNoPropMd}}}}, |
| {err: "invalid value", seed: &Map{m: map[Key]tagContent{{name: "key"}: {"Приве́т", ttlNoPropMd}}}}, |
| {err: "invalid value", seed: &Map{m: map[Key]tagContent{{name: "key"}: {strings.Repeat("a", 256), ttlNoPropMd}}}}, |
| } |
| |
| for i, tt := range tests { |
| ctx := NewContext(context.Background(), tt.seed) |
| ctx, err := New(ctx) |
| |
| if tt.err != "" { |
| if err == nil { |
| t.Errorf("#%d: got nil error; want %q", i, tt.err) |
| continue |
| } else if s, substr := err.Error(), tt.err; !strings.Contains(s, substr) { |
| t.Errorf("#%d:\ngot %q\nwant %q", i, s, substr) |
| } |
| continue |
| } |
| if err != nil { |
| t.Errorf("#%d: got %q want nil", i, err) |
| continue |
| } |
| m := FromContext(ctx) |
| if m == nil { |
| t.Errorf("#%d: got nil map", i) |
| continue |
| } |
| } |
| } |
| |
| func makeTestTagMap(ids ...int) *Map { |
| m := newMap() |
| for _, v := range ids { |
| k, _ := NewKey(fmt.Sprintf("k%d", v)) |
| m.m[k] = tagContent{fmt.Sprintf("v%d", v), ttlUnlimitedPropMd} |
| } |
| return m |
| } |
| |
| func makeTestTagMapWithMetadata(tcs ...tagContent) *Map { |
| m := newMap() |
| for _, tc := range tcs { |
| k, _ := NewKey(fmt.Sprintf("k%s", tc.value)) |
| m.m[k] = tc |
| } |
| return m |
| } |