1package jd 2 3import ( 4 "testing" 5) 6 7func TestMultisetJson(t *testing.T) { 8 cases := []struct { 9 name string 10 metadata Metadata 11 given string 12 want string 13 }{{ 14 name: "empty mulitset", 15 metadata: MULTISET, 16 given: `[]`, 17 want: `[]`, 18 }, { 19 name: "empty multiset with space", 20 metadata: MULTISET, 21 given: ` [ ] `, 22 want: `[]`, 23 }, { 24 name: "ordered multiset", 25 metadata: MULTISET, 26 given: `[1,2,3]`, 27 want: `[1,2,3]`, 28 }, { 29 name: "ordered multiset with space", 30 metadata: MULTISET, 31 given: ` [1, 2, 3] `, 32 want: `[1,2,3]`, 33 }, { 34 name: "multset with multiple duplicates", 35 metadata: MULTISET, 36 given: `[1,1,1]`, 37 want: `[1,1,1]`, 38 }} 39 40 for _, c := range cases { 41 t.Run(c.name, func(t *testing.T) { 42 ctx := newTestContext(t). 43 withMetadata(c.metadata) 44 checkJson(ctx, c.given, c.want) 45 }) 46 } 47} 48 49func TestMultisetEquals(t *testing.T) { 50 cases := []struct { 51 name string 52 metadata Metadata 53 a string 54 b string 55 }{{ 56 name: "empty multisets", 57 metadata: MULTISET, 58 a: `[]`, 59 b: `[]`, 60 }, { 61 name: "different ordered multisets 1", 62 metadata: MULTISET, 63 a: `[1,2,3]`, 64 b: `[3,2,1]`, 65 }, { 66 name: "different ordered multisets 2", 67 metadata: MULTISET, 68 a: `[1,2,3]`, 69 b: `[2,3,1]`, 70 }, { 71 name: "different ordered multisets 2", 72 metadata: MULTISET, 73 a: `[1,2,3]`, 74 b: `[1,3,2]`, 75 }, { 76 name: "multsets with empty objects", 77 metadata: MULTISET, 78 a: `[{},{}]`, 79 b: `[{},{}]`, 80 }, { 81 name: "nested multisets", 82 metadata: MULTISET, 83 a: `[[1,2],[3,4]]`, 84 b: `[[2,1],[4,3]]`, 85 }} 86 87 for _, c := range cases { 88 t.Run(c.name, func(t *testing.T) { 89 // TODO: implement multiset equals with metadata 90 ctx := newTestContext(t). 91 withMetadata(c.metadata) 92 checkEqual(ctx, c.a, c.b) 93 }) 94 } 95} 96 97func TestMultisetNotEquals(t *testing.T) { 98 cases := []struct { 99 name string 100 metadata Metadata 101 a string 102 b string 103 }{{ 104 name: "empty multiset and multiset with number", 105 metadata: MULTISET, 106 a: `[]`, 107 b: `[1]`, 108 }, { 109 name: "multisets with different numbers", 110 metadata: MULTISET, 111 a: `[1,2,3]`, 112 b: `[1,2,2]`, 113 }, { 114 name: "multiset missing a number", 115 metadata: MULTISET, 116 a: `[1,2,3]`, 117 b: `[1,2]`, 118 }, { 119 name: "nested multisets with different numbers", 120 a: `[[],[1]]`, 121 b: `[[],[2]]`, 122 metadata: MULTISET, 123 }} 124 125 for _, c := range cases { 126 t.Run(c.name, func(t *testing.T) { 127 ctx := newTestContext(t). 128 withMetadata(c.metadata) 129 checkNotEqual(ctx, c.a, c.b) 130 }) 131 } 132} 133 134func TestMultisetDiff(t *testing.T) { 135 cases := []struct { 136 name string 137 metadata Metadata 138 a string 139 b string 140 want []string 141 }{{ 142 name: "two empty multisets", 143 metadata: MULTISET, 144 a: `[]`, 145 b: `[]`, 146 want: s(``), 147 }, { 148 name: "two multisets with different numbers", 149 metadata: MULTISET, 150 a: `[1]`, 151 b: `[1,2]`, 152 want: s( 153 `@ [["multiset"],{}]`, 154 `+ 2`, 155 ), 156 }, { 157 name: "two multisets with the same number", 158 metadata: MULTISET, 159 a: `[1,2]`, 160 b: `[1,2]`, 161 want: s(``), 162 }, { 163 name: "adding two numbers", 164 metadata: MULTISET, 165 a: `[1]`, 166 b: `[1,2,2]`, 167 want: s( 168 `@ [["multiset"],{}]`, 169 `+ 2`, 170 `+ 2`, 171 ), 172 }, { 173 name: "removing a number", 174 metadata: MULTISET, 175 a: `[1,2,3]`, 176 b: `[1,3]`, 177 want: s( 178 `@ [["multiset"],{}]`, 179 `- 2`, 180 ), 181 }, { 182 name: "replacing one object with another", 183 metadata: MULTISET, 184 a: `[{"a":1}]`, 185 b: `[{"a":2}]`, 186 want: s( 187 `@ [["multiset"],{}]`, 188 `- {"a":1}`, 189 `+ {"a":2}`, 190 ), 191 }, { 192 name: "replacing two objects with one object", 193 metadata: MULTISET, 194 a: `[{"a":1},{"a":1}]`, 195 b: `[{"a":2}]`, 196 want: s( 197 `@ [["multiset"],{}]`, 198 `- {"a":1}`, 199 `- {"a":1}`, 200 `+ {"a":2}`, 201 ), 202 }, { 203 name: "replacing three strings repeated with one string", 204 metadata: MULTISET, 205 a: `["foo","foo","bar"]`, 206 b: `["baz"]`, 207 want: s( 208 `@ [["multiset"],{}]`, 209 `- "bar"`, 210 `- "foo"`, 211 `- "foo"`, 212 `+ "baz"`, 213 ), 214 }, { 215 name: "replacing one string with three repeated", 216 metadata: MULTISET, 217 a: `["foo"]`, 218 b: `["bar","baz","bar"]`, 219 want: s( 220 `@ [["multiset"],{}]`, 221 `- "foo"`, 222 `+ "bar"`, 223 `+ "bar"`, 224 `+ "baz"`, 225 ), 226 }, { 227 name: "replacing multiset with array", 228 metadata: MULTISET, 229 a: `{}`, 230 b: `[]`, 231 want: s( 232 `@ []`, 233 `- {}`, 234 `+ []`, 235 ), 236 }} 237 238 for _, c := range cases { 239 t.Run(c.name, func(t *testing.T) { 240 ctx := newTestContext(t). 241 withMetadata(c.metadata) 242 checkDiff(ctx, c.a, c.b, c.want...) 243 }) 244 } 245} 246 247func TestMultisetPatch(t *testing.T) { 248 cases := []struct { 249 name string 250 metadata Metadata 251 given string 252 patch []string 253 want string 254 }{{ 255 name: "empty patch on empty multiset", 256 metadata: MULTISET, 257 given: `[]`, 258 patch: s(``), 259 want: `[]`, 260 }, { 261 name: "add a number", 262 metadata: MULTISET, 263 given: `[1]`, 264 patch: s( 265 `@ [["multiset"],{}]`, 266 `+ 2`, 267 ), 268 want: `[1,2]`, 269 }, { 270 name: "empty patch on multiset with numbers", 271 metadata: MULTISET, 272 given: `[1,2]`, 273 patch: s(``), 274 want: `[1,2]`, 275 }, { 276 name: "add two numbers", 277 metadata: MULTISET, 278 given: `[1]`, 279 patch: s( 280 `@ [["multiset"],{}]`, 281 `+ 2`, 282 `+ 2`, 283 ), 284 want: `[1,2,2]`, 285 }, { 286 name: "remove a number", 287 metadata: MULTISET, 288 given: `[1,2,3]`, 289 patch: s( 290 `@ [["multiset"],{}]`, 291 `- 2`, 292 ), 293 want: `[1,3]`, 294 }, { 295 name: "replace one object with another", 296 metadata: MULTISET, 297 given: `[{"a":1}]`, 298 patch: s( 299 `@ [["multiset"],{}]`, 300 `- {"a":1}`, 301 `+ {"a":2}`, 302 ), 303 want: `[{"a":2}]`, 304 }, { 305 name: "remove two objects and add one", 306 metadata: MULTISET, 307 given: `[{"a":1},{"a":1}]`, 308 patch: s( 309 `@ [["multiset"],{}]`, 310 `- {"a":1}`, 311 `- {"a":1}`, 312 `+ {"a":2}`, 313 ), 314 want: `[{"a":2}]`, 315 }, { 316 name: "remove three objects repeated and add one", 317 metadata: MULTISET, 318 given: `["foo","foo","bar"]`, 319 patch: s( 320 `@ [["multiset"],{}]`, 321 `- "bar"`, 322 `- "foo"`, 323 `- "foo"`, 324 `+ "baz"`, 325 ), 326 want: `["baz"]`, 327 }, { 328 name: "remove one object and add three repeated", 329 metadata: MULTISET, 330 given: `["foo"]`, 331 patch: s( 332 `@ [["multiset"],{}]`, 333 `- "foo"`, 334 `+ "bar"`, 335 `+ "bar"`, 336 `+ "baz"`, 337 ), 338 want: `["bar","baz","bar"]`, 339 }, { 340 name: "replace multiset with array", 341 metadata: MULTISET, 342 given: `{}`, 343 patch: s( 344 `@ []`, 345 `- {}`, 346 `+ []`, 347 ), 348 want: `[]`, 349 }} 350 351 for _, c := range cases { 352 t.Run(c.name, func(t *testing.T) { 353 // TODO: implement multiset patch with metadata 354 ctx := newTestContext(t). 355 withMetadata(c.metadata) 356 checkPatch(ctx, c.given, c.want, c.patch...) 357 }) 358 } 359} 360 361func TestMultisetPatchError(t *testing.T) { 362 cases := []struct { 363 name string 364 metadata Metadata 365 given string 366 patch []string 367 }{{ 368 name: "remove number from empty multiset", 369 metadata: MULTISET, 370 given: `[]`, 371 patch: s( 372 `@ [{}]`, 373 `- 1`, 374 ), 375 }, { 376 name: "remove a single number twice", 377 metadata: MULTISET, 378 given: `[1]`, 379 patch: s( 380 `@ [{}]`, 381 `- 1`, 382 `- 1`, 383 ), 384 }, { 385 name: "remove an object when there is a multiset", 386 metadata: MULTISET, 387 given: `[]`, 388 patch: s( 389 `@ []`, 390 `- {}`, 391 ), 392 }} 393 394 for _, c := range cases { 395 t.Run(c.name, func(t *testing.T) { 396 ctx := newTestContext(t). 397 withMetadata(c.metadata) 398 checkPatchError(ctx, c.given, c.patch...) 399 }) 400 } 401} 402