1// Copyright 2014 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package datastore 16 17import ( 18 "bytes" 19 "encoding/gob" 20 "encoding/json" 21 "testing" 22) 23 24func TestEqual(t *testing.T) { 25 testCases := []struct { 26 x, y *Key 27 equal bool 28 }{ 29 { 30 x: nil, 31 y: nil, 32 equal: true, 33 }, 34 { 35 x: &Key{Kind: "kindA"}, 36 y: &Key{Kind: "kindA"}, 37 equal: true, 38 }, 39 { 40 x: &Key{Kind: "kindA", Name: "nameA"}, 41 y: &Key{Kind: "kindA", Name: "nameA"}, 42 equal: true, 43 }, 44 { 45 x: &Key{Kind: "kindA", Name: "nameA", Namespace: "gopherspace"}, 46 y: &Key{Kind: "kindA", Name: "nameA", Namespace: "gopherspace"}, 47 equal: true, 48 }, 49 { 50 x: &Key{Kind: "kindA", ID: 1337, Parent: &Key{Kind: "kindX", Name: "nameX"}}, 51 y: &Key{Kind: "kindA", ID: 1337, Parent: &Key{Kind: "kindX", Name: "nameX"}}, 52 equal: true, 53 }, 54 { 55 x: &Key{Kind: "kindA", Name: "nameA"}, 56 y: &Key{Kind: "kindB", Name: "nameA"}, 57 equal: false, 58 }, 59 { 60 x: &Key{Kind: "kindA", Name: "nameA"}, 61 y: &Key{Kind: "kindA", Name: "nameB"}, 62 equal: false, 63 }, 64 { 65 x: &Key{Kind: "kindA", Name: "nameA"}, 66 y: &Key{Kind: "kindA", ID: 1337}, 67 equal: false, 68 }, 69 { 70 x: &Key{Kind: "kindA", Name: "nameA"}, 71 y: &Key{Kind: "kindA", Name: "nameA", Namespace: "gopherspace"}, 72 equal: false, 73 }, 74 { 75 x: &Key{Kind: "kindA", ID: 1337, Parent: &Key{Kind: "kindX", Name: "nameX"}}, 76 y: &Key{Kind: "kindA", ID: 1337, Parent: &Key{Kind: "kindY", Name: "nameX"}}, 77 equal: false, 78 }, 79 { 80 x: &Key{Kind: "kindA", ID: 1337, Parent: &Key{Kind: "kindX", Name: "nameX"}}, 81 y: &Key{Kind: "kindA", ID: 1337}, 82 equal: false, 83 }, 84 } 85 86 for _, tt := range testCases { 87 if got := tt.x.Equal(tt.y); got != tt.equal { 88 t.Errorf("Equal(%v, %v) = %t; want %t", tt.x, tt.y, got, tt.equal) 89 } 90 if got := tt.y.Equal(tt.x); got != tt.equal { 91 t.Errorf("Equal(%v, %v) = %t; want %t", tt.y, tt.x, got, tt.equal) 92 } 93 } 94} 95 96func TestEncoding(t *testing.T) { 97 testCases := []struct { 98 k *Key 99 valid bool 100 }{ 101 { 102 k: nil, 103 valid: false, 104 }, 105 { 106 k: &Key{}, 107 valid: false, 108 }, 109 { 110 k: &Key{Kind: "kindA"}, 111 valid: true, 112 }, 113 { 114 k: &Key{Kind: "kindA", Namespace: "gopherspace"}, 115 valid: true, 116 }, 117 { 118 k: &Key{Kind: "kindA", Name: "nameA"}, 119 valid: true, 120 }, 121 { 122 k: &Key{Kind: "kindA", ID: 1337}, 123 valid: true, 124 }, 125 { 126 k: &Key{Kind: "kindA", Name: "nameA", ID: 1337}, 127 valid: false, 128 }, 129 { 130 k: &Key{Kind: "kindA", Parent: &Key{Kind: "kindB", Name: "nameB"}}, 131 valid: true, 132 }, 133 { 134 k: &Key{Kind: "kindA", Parent: &Key{Kind: "kindB"}}, 135 valid: false, 136 }, 137 { 138 k: &Key{Kind: "kindA", Parent: &Key{Kind: "kindB", Name: "nameB", Namespace: "gopherspace"}}, 139 valid: false, 140 }, 141 } 142 143 for _, tt := range testCases { 144 if got := tt.k.valid(); got != tt.valid { 145 t.Errorf("valid(%v) = %t; want %t", tt.k, got, tt.valid) 146 } 147 148 // Check encoding/decoding for valid keys. 149 if !tt.valid { 150 continue 151 } 152 enc := tt.k.Encode() 153 dec, err := DecodeKey(enc) 154 if err != nil { 155 t.Errorf("DecodeKey(%q) from %v: %v", enc, tt.k, err) 156 continue 157 } 158 if !tt.k.Equal(dec) { 159 t.Logf("Proto: %s", keyToProto(tt.k)) 160 t.Errorf("Decoded key %v not equal to %v", dec, tt.k) 161 } 162 163 b, err := json.Marshal(tt.k) 164 if err != nil { 165 t.Errorf("json.Marshal(%v): %v", tt.k, err) 166 continue 167 } 168 key := &Key{} 169 if err := json.Unmarshal(b, key); err != nil { 170 t.Errorf("json.Unmarshal(%s) for key %v: %v", b, tt.k, err) 171 continue 172 } 173 if !tt.k.Equal(key) { 174 t.Errorf("JSON decoded key %v not equal to %v", dec, tt.k) 175 } 176 177 buf := &bytes.Buffer{} 178 gobEnc := gob.NewEncoder(buf) 179 if err := gobEnc.Encode(tt.k); err != nil { 180 t.Errorf("gobEnc.Encode(%v): %v", tt.k, err) 181 continue 182 } 183 gobDec := gob.NewDecoder(buf) 184 key = &Key{} 185 if err := gobDec.Decode(key); err != nil { 186 t.Errorf("gobDec.Decode() for key %v: %v", tt.k, err) 187 } 188 if !tt.k.Equal(key) { 189 t.Errorf("gob decoded key %v not equal to %v", dec, tt.k) 190 } 191 } 192} 193 194func TestInvalidKeyDecode(t *testing.T) { 195 // Check that decoding an invalid key returns an err and doesn't panic. 196 enc := NameKey("Kind", "Foo", nil).Encode() 197 198 invalid := []string{ 199 "", 200 "Laboratorio", 201 enc + "Junk", 202 enc[:len(enc)-4], 203 } 204 for _, enc := range invalid { 205 key, err := DecodeKey(enc) 206 if err == nil || key != nil { 207 t.Errorf("DecodeKey(%q) = %v, %v; want nil, error", enc, key, err) 208 } 209 } 210} 211