1
16
17 package cached_test
18
19 import (
20 "bytes"
21 "encoding/json"
22 "errors"
23 "fmt"
24 "math/rand"
25 "sort"
26 "strings"
27 "sync"
28 "testing"
29 "time"
30
31 "k8s.io/kube-openapi/pkg/cached"
32 )
33
34 func TestDataFunc(t *testing.T) {
35 count := 0
36 source := cached.Func(func() ([]byte, string, error) {
37 count += 1
38 return []byte("source"), "source", nil
39 })
40 if _, _, err := source.Get(); err != nil {
41 t.Fatalf("unexpected error: %v", err)
42 }
43 if _, _, err := source.Get(); err != nil {
44 t.Fatalf("unexpected error: %v", err)
45 }
46 if count != 2 {
47 t.Fatalf("Expected function called twice, called: %v", count)
48 }
49 }
50
51 func TestDataFuncError(t *testing.T) {
52 count := 0
53 source := cached.Func(func() ([]byte, string, error) {
54 count += 1
55 return nil, "", errors.New("source error")
56 })
57 if _, _, err := source.Get(); err == nil {
58 t.Fatalf("expected error, found none")
59 }
60 if _, _, err := source.Get(); err == nil {
61 t.Fatalf("expected error, found none")
62 }
63 if count != 2 {
64 t.Fatalf("Expected function called twice, called: %v", count)
65 }
66 }
67
68 func TestDataFuncAlternate(t *testing.T) {
69 count := 0
70 source := cached.Func(func() ([]byte, string, error) {
71 count += 1
72 if count%2 == 0 {
73 return nil, "", errors.New("source error")
74 }
75 return []byte("source"), "source", nil
76 })
77 if _, _, err := source.Get(); err != nil {
78 t.Fatalf("unexpected error: %v", err)
79 }
80 if _, _, err := source.Get(); err == nil {
81 t.Fatalf("expected error, found none")
82 }
83 if _, _, err := source.Get(); err != nil {
84 t.Fatalf("unexpected error: %v", err)
85 }
86 if _, _, err := source.Get(); err == nil {
87 t.Fatalf("expected error, found none")
88 }
89 if count != 4 {
90 t.Fatalf("Expected function called 4x, called: %v", count)
91 }
92 }
93
94 func TestOnce(t *testing.T) {
95 count := 0
96 source := cached.Once(cached.Func(func() ([]byte, string, error) {
97 count += 1
98 return []byte("source"), "source", nil
99 }))
100 if _, _, err := source.Get(); err != nil {
101 t.Fatalf("unexpected error: %v", err)
102 }
103 if _, _, err := source.Get(); err != nil {
104 t.Fatalf("unexpected error: %v", err)
105 }
106 if count != 1 {
107 t.Fatalf("Expected function called once, called: %v", count)
108 }
109 }
110
111 func TestOnceError(t *testing.T) {
112 count := 0
113 source := cached.Once(cached.Func(func() ([]byte, string, error) {
114 count += 1
115 return nil, "", errors.New("source error")
116 }))
117 if _, _, err := source.Get(); err == nil {
118 t.Fatalf("expected error, found none")
119 }
120 if _, _, err := source.Get(); err == nil {
121 t.Fatalf("expected error, found none")
122 }
123 if count != 1 {
124 t.Fatalf("Expected function called once, called: %v", count)
125 }
126 }
127
128 func TestResultGet(t *testing.T) {
129 source := cached.Static([]byte("source"), "etag")
130 value, etag, err := source.Get()
131 if err != nil {
132 t.Fatalf("unexpected error: %v", err)
133 }
134 if want := "source"; string(value) != want {
135 t.Fatalf("expected value %q, got %q", want, string(value))
136 }
137 if want := "etag"; etag != want {
138 t.Fatalf("expected etag %q, got %q", want, etag)
139 }
140 }
141
142 func TestResultGetError(t *testing.T) {
143 source := cached.Result[[]byte]{Err: errors.New("source error")}
144 value, etag, err := source.Get()
145 if err == nil {
146 t.Fatalf("expected error, found none")
147 }
148 if value != nil {
149 t.Fatalf("expected nil value, got %v", value)
150 }
151 if etag != "" {
152 t.Fatalf("expected empty etag, got %q", etag)
153 }
154 }
155
156 func TestTransform(t *testing.T) {
157 sourceCount := 0
158 source := cached.Func(func() ([]byte, string, error) {
159 sourceCount += 1
160 return []byte("source"), "source", nil
161 })
162 transformerCount := 0
163 transformer := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
164 transformerCount += 1
165 if err != nil {
166 return nil, "", err
167 }
168 return []byte("transformed " + string(value)), "transformed " + etag, nil
169 }, source)
170 if _, _, err := transformer.Get(); err != nil {
171 t.Fatalf("unexpected error: %v", err)
172 }
173 if _, _, err := transformer.Get(); err != nil {
174 t.Fatalf("unexpected error: %v", err)
175 }
176 if sourceCount != 2 {
177 t.Fatalf("Expected source function called twice, called: %v", sourceCount)
178 }
179 if transformerCount != 1 {
180 t.Fatalf("Expected transformer function called once, called: %v", transformerCount)
181 }
182 }
183
184 func TestTransformChained(t *testing.T) {
185 sourceCount := 0
186 source := cached.Func(func() ([]byte, string, error) {
187 sourceCount += 1
188 return []byte("source"), "source", nil
189 })
190 transformer1Count := 0
191 transformer1 := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
192 transformer1Count += 1
193 if err != nil {
194 return nil, "", err
195 }
196 return []byte("transformed " + string(value)), etag, nil
197 }, source)
198 transformer2Count := 0
199 transformer2 := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
200 transformer2Count += 1
201 if err != nil {
202 return nil, "", err
203 }
204 return []byte("transformed " + string(value)), etag, nil
205 }, transformer1)
206 transformer3Count := 0
207 transformer3 := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
208 transformer3Count += 1
209 if err != nil {
210 return nil, "", err
211 }
212 return []byte("transformed " + string(value)), etag, nil
213 }, transformer2)
214 if _, _, err := transformer3.Get(); err != nil {
215 t.Fatalf("unexpected error: %v", err)
216 }
217 result, etag, err := transformer3.Get()
218 if err != nil {
219 t.Fatalf("unexpected error: %v", err)
220 }
221 if want := "transformed transformed transformed source"; string(result) != want {
222 t.Fatalf("expected data = %v, got %v", want, string(result))
223 }
224 if want := "source"; etag != want {
225 t.Fatalf("expected etag = %v, got %v", want, etag)
226 }
227 if sourceCount != 2 {
228 t.Fatalf("Expected source function called twice, called: %v", sourceCount)
229 }
230 if transformer1Count != 1 {
231 t.Fatalf("Expected transformer function called once, called: %v", transformer1Count)
232 }
233 if transformer2Count != 1 {
234 t.Fatalf("Expected transformer function called once, called: %v", transformer2Count)
235 }
236 if transformer3Count != 1 {
237 t.Fatalf("Expected transformer function called once, called: %v", transformer3Count)
238 }
239 }
240
241 func TestTransformError(t *testing.T) {
242 sourceCount := 0
243 source := cached.Func(func() ([]byte, string, error) {
244 sourceCount += 1
245 return []byte("source"), "source", nil
246 })
247 transformerCount := 0
248 transformer := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
249 transformerCount += 1
250 return nil, "", errors.New("transformer error")
251 }, source)
252 if _, _, err := transformer.Get(); err == nil {
253 t.Fatalf("expected error, none found")
254 }
255 if _, _, err := transformer.Get(); err == nil {
256 t.Fatalf("expected error, none found")
257 }
258 if sourceCount != 2 {
259 t.Fatalf("Expected source function called twice, called: %v", sourceCount)
260 }
261 if transformerCount != 2 {
262 t.Fatalf("Expected transformer function called twice, called: %v", transformerCount)
263 }
264 }
265
266 func TestTransformSourceError(t *testing.T) {
267 sourceCount := 0
268 source := cached.Func(func() ([]byte, string, error) {
269 sourceCount += 1
270 return nil, "", errors.New("source error")
271 })
272 transformerCount := 0
273 transformer := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
274 transformerCount += 1
275 if err != nil {
276 return nil, "", err
277 }
278 return []byte("transformed " + string(value)), "transformed " + etag, nil
279 }, source)
280 if _, _, err := transformer.Get(); err == nil {
281 t.Fatalf("expected error, none found")
282 }
283 if _, _, err := transformer.Get(); err == nil {
284 t.Fatalf("expected error, none found")
285 }
286 if sourceCount != 2 {
287 t.Fatalf("Expected source function called twice, called: %v", sourceCount)
288 }
289 if transformerCount != 2 {
290 t.Fatalf("Expected transformer function called twice, called: %v", transformerCount)
291 }
292 }
293
294 func TestTransformAlternateSourceError(t *testing.T) {
295 sourceCount := 0
296 source := cached.Func(func() ([]byte, string, error) {
297 sourceCount += 1
298 if sourceCount%2 == 0 {
299 return nil, "", errors.New("source error")
300 }
301 return []byte("source"), "source", nil
302 })
303 transformerCount := 0
304 transformer := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
305 transformerCount += 1
306 if err != nil {
307 return nil, "", err
308 }
309 return []byte("transformed " + string(value)), "transformed " + etag, err
310 }, source)
311 result, etag, err := transformer.Get()
312 if err != nil {
313 t.Fatalf("unexpected error: %v", err)
314 }
315 if want := "transformed source"; string(result) != want {
316 t.Fatalf("expected data = %v, got %v", want, string(result))
317 }
318 if want := "transformed source"; etag != want {
319 t.Fatalf("expected etag = %v, got %v", want, etag)
320 }
321 if _, _, err := transformer.Get(); err == nil {
322 t.Fatalf("expected error, none found")
323 }
324 result, etag, err = transformer.Get()
325 if err != nil {
326 t.Fatalf("unexpected error: %v", err)
327 }
328 if want := "transformed source"; string(result) != want {
329 t.Fatalf("expected data = %v, got %v", want, string(result))
330 }
331 if want := "transformed source"; etag != want {
332 t.Fatalf("expected etag = %v, got %v", want, etag)
333 }
334 if _, _, err := transformer.Get(); err == nil {
335 t.Fatalf("expected error, none found")
336 }
337 if sourceCount != 4 {
338 t.Fatalf("Expected source function called 4x, called: %v", sourceCount)
339 }
340 if transformerCount != 4 {
341 t.Fatalf("Expected transformer function called 4x, called: %v", transformerCount)
342 }
343
344 }
345
346 func TestMerge(t *testing.T) {
347 source1Count := 0
348 source1 := cached.Func(func() ([]byte, string, error) {
349 source1Count += 1
350 return []byte("source1"), "source1", nil
351 })
352 source2Count := 0
353 source2 := cached.Func(func() ([]byte, string, error) {
354 source2Count += 1
355 return []byte("source2"), "source2", nil
356 })
357 mergerCount := 0
358 merger := cached.Merge(func(results map[string]cached.Result[[]byte]) ([]byte, string, error) {
359 mergerCount += 1
360 d := []string{}
361 e := []string{}
362 for _, result := range results {
363 if result.Err != nil {
364 return nil, "", result.Err
365 }
366 d = append(d, string(result.Value))
367 e = append(e, result.Etag)
368 }
369 sort.Strings(d)
370 sort.Strings(e)
371 return []byte("merged " + strings.Join(d, " and ")), "merged " + strings.Join(e, " and "), nil
372 }, map[string]cached.Value[[]byte]{
373 "source1": source1,
374 "source2": source2,
375 })
376 if _, _, err := merger.Get(); err != nil {
377 t.Fatalf("unexpected error: %v", err)
378 }
379 result, etag, err := merger.Get()
380 if err != nil {
381 t.Fatalf("unexpected error: %v", err)
382 }
383 if want := "merged source1 and source2"; string(result) != want {
384 t.Fatalf("expected data = %v, got %v", want, string(result))
385 }
386 if want := "merged source1 and source2"; etag != want {
387 t.Fatalf("expected etag = %v, got %v", want, etag)
388 }
389
390 if source1Count != 2 {
391 t.Fatalf("Expected source function called twice, called: %v", source1Count)
392 }
393 if source2Count != 2 {
394 t.Fatalf("Expected source function called twice, called: %v", source2Count)
395 }
396 if mergerCount != 1 {
397 t.Fatalf("Expected merger function called once, called: %v", mergerCount)
398 }
399 }
400
401 func TestMergeError(t *testing.T) {
402 source1Count := 0
403 source1 := cached.Func(func() ([]byte, string, error) {
404 source1Count += 1
405 return []byte("source1"), "source1", nil
406 })
407 source2Count := 0
408 source2 := cached.Func(func() ([]byte, string, error) {
409 source2Count += 1
410 return []byte("source2"), "source2", nil
411 })
412 mergerCount := 0
413 merger := cached.Merge(func(results map[string]cached.Result[[]byte]) ([]byte, string, error) {
414 mergerCount += 1
415 return nil, "", errors.New("merger error")
416 }, map[string]cached.Value[[]byte]{
417 "source1": source1,
418 "source2": source2,
419 })
420 if _, _, err := merger.Get(); err == nil {
421 t.Fatalf("expected error, none found")
422 }
423 if _, _, err := merger.Get(); err == nil {
424 t.Fatalf("expected error, none found")
425 }
426 if source1Count != 2 {
427 t.Fatalf("Expected source function called twice, called: %v", source1Count)
428 }
429 if source2Count != 2 {
430 t.Fatalf("Expected source function called twice, called: %v", source2Count)
431 }
432 if mergerCount != 2 {
433 t.Fatalf("Expected merger function called twice, called: %v", mergerCount)
434 }
435 }
436
437 func TestMergeSourceError(t *testing.T) {
438 source1Count := 0
439 source1 := cached.Func(func() ([]byte, string, error) {
440 source1Count += 1
441 return nil, "", errors.New("source1 error")
442 })
443 source2Count := 0
444 source2 := cached.Func(func() ([]byte, string, error) {
445 source2Count += 1
446 return []byte("source2"), "source2", nil
447 })
448 mergerCount := 0
449 merger := cached.Merge(func(results map[string]cached.Result[[]byte]) ([]byte, string, error) {
450 mergerCount += 1
451 d := []string{}
452 e := []string{}
453 for _, result := range results {
454 if result.Err != nil {
455 return nil, "", result.Err
456 }
457 d = append(d, string(result.Value))
458 e = append(e, result.Etag)
459 }
460 sort.Strings(d)
461 sort.Strings(e)
462 return []byte("merged " + strings.Join(d, " and ")), "merged " + strings.Join(e, " and "), nil
463 }, map[string]cached.Value[[]byte]{
464 "source1": source1,
465 "source2": source2,
466 })
467 if _, _, err := merger.Get(); err == nil {
468 t.Fatalf("expected error, none found")
469 }
470 if _, _, err := merger.Get(); err == nil {
471 t.Fatalf("expected error, none found")
472 }
473 if source1Count != 2 {
474 t.Fatalf("Expected source function called twice, called: %v", source1Count)
475 }
476 if source2Count != 2 {
477 t.Fatalf("Expected source function called twice, called: %v", source2Count)
478 }
479 if mergerCount != 2 {
480 t.Fatalf("Expected merger function called twice, called: %v", mergerCount)
481 }
482 }
483
484 func TestMergeAlternateSourceError(t *testing.T) {
485 source1Count := 0
486 source1 := cached.Func(func() ([]byte, string, error) {
487 source1Count += 1
488 if source1Count%2 == 0 {
489 return nil, "", errors.New("source1 error")
490 } else {
491 return []byte("source1"), "source1", nil
492 }
493 })
494 source2Count := 0
495 source2 := cached.Func(func() ([]byte, string, error) {
496 source2Count += 1
497 return []byte("source2"), "source2", nil
498 })
499 mergerCount := 0
500 merger := cached.Merge(func(results map[string]cached.Result[[]byte]) ([]byte, string, error) {
501 mergerCount += 1
502 d := []string{}
503 e := []string{}
504 for _, result := range results {
505 if result.Err != nil {
506 return nil, "", result.Err
507 }
508 d = append(d, string(result.Value))
509 e = append(e, result.Etag)
510 }
511 sort.Strings(d)
512 sort.Strings(e)
513 return []byte("merged " + strings.Join(d, " and ")), "merged " + strings.Join(e, " and "), nil
514 }, map[string]cached.Value[[]byte]{
515 "source1": source1,
516 "source2": source2,
517 })
518 result, etag, err := merger.Get()
519 if err != nil {
520 t.Fatalf("unexpected error: %v", err)
521 }
522 if want := "merged source1 and source2"; string(result) != want {
523 t.Fatalf("expected data = %v, got %v", want, string(result))
524 }
525 if want := "merged source1 and source2"; etag != want {
526 t.Fatalf("expected etag = %v, got %v", want, etag)
527 }
528 if _, _, err := merger.Get(); err == nil {
529 t.Fatalf("expected error, none found")
530 }
531 result, etag, err = merger.Get()
532 if err != nil {
533 t.Fatalf("unexpected error: %v", err)
534 }
535 if want := "merged source1 and source2"; string(result) != want {
536 t.Fatalf("expected data = %v, got %v", want, string(result))
537 }
538 if want := "merged source1 and source2"; etag != want {
539 t.Fatalf("expected etag = %v, got %v", want, etag)
540 }
541 if _, _, err := merger.Get(); err == nil {
542 t.Fatalf("expected error, none found")
543 }
544 if source1Count != 4 {
545 t.Fatalf("Expected source function called 4x, called: %v", source1Count)
546 }
547 if source2Count != 4 {
548 t.Fatalf("Expected source function called 4x, called: %v", source2Count)
549 }
550 if mergerCount != 4 {
551 t.Fatalf("Expected merger function called 4x, called: %v", mergerCount)
552 }
553 }
554
555 func TestAtomic(t *testing.T) {
556 sourceDataCount := 0
557 sourceData := cached.Func(func() ([]byte, string, error) {
558 sourceDataCount += 1
559 return []byte("source"), "source", nil
560 })
561 sourceData2Count := 0
562 sourceData2 := cached.Func(func() ([]byte, string, error) {
563 sourceData2Count += 1
564 return []byte("source2"), "source2", nil
565 })
566 sourceErrCount := 0
567 sourceErr := cached.Func(func() ([]byte, string, error) {
568 sourceErrCount += 1
569 return nil, "", errors.New("source error")
570 })
571
572 replaceable := &cached.Atomic[[]byte]{}
573 replaceable.Store(sourceErr)
574 if _, _, err := replaceable.Get(); err == nil {
575 t.Fatalf("expected error, found none")
576 }
577
578 replaceable.Store(sourceData)
579 result, etag, err := replaceable.Get()
580 if err != nil {
581 t.Fatalf("unexpected error: %v", err)
582 }
583 if want := "source"; string(result) != want {
584 t.Fatalf("expected data = %v, got %v", want, string(result))
585 }
586 if want := "source"; etag != want {
587 t.Fatalf("expected etag = %v, got %v", want, etag)
588 }
589
590
591 replaceable.Store(sourceData)
592 result, etag, err = replaceable.Get()
593 if err != nil {
594 t.Fatalf("unexpected error: %v", err)
595 }
596 if want := "source"; string(result) != want {
597 t.Fatalf("expected data = %v, got %v", want, string(result))
598 }
599 if want := "source"; etag != want {
600 t.Fatalf("expected etag = %v, got %v", want, etag)
601 }
602
603
604 replaceable.Store(sourceErr)
605 result, etag, err = replaceable.Get()
606 if err == nil {
607 t.Fatalf("unexpected success")
608 }
609
610 replaceable.Store(sourceData2)
611 result, etag, err = replaceable.Get()
612 if err != nil {
613 t.Fatalf("unexpected error: %v", err)
614 }
615 if want := "source2"; string(result) != want {
616 t.Fatalf("expected data = %v, got %v", want, string(result))
617 }
618 if want := "source2"; etag != want {
619 t.Fatalf("expected etag = %v, got %v", want, etag)
620 }
621 if sourceDataCount != 2 {
622 t.Fatalf("Expected sourceData function called twice, called: %v", sourceDataCount)
623 }
624 if sourceData2Count != 1 {
625 t.Fatalf("Expected sourceData2 function called once, called: %v", sourceData2Count)
626 }
627 if sourceErrCount != 2 {
628 t.Fatalf("Expected error source function called once, called: %v", sourceErrCount)
629 }
630 }
631
632 func TestLastSuccess(t *testing.T) {
633 sourceDataCount := 0
634 sourceData := cached.Func(func() ([]byte, string, error) {
635 sourceDataCount += 1
636 return []byte("source"), "source", nil
637 })
638 sourceData2Count := 0
639 sourceData2 := cached.Func(func() ([]byte, string, error) {
640 sourceData2Count += 1
641 return []byte("source2"), "source2", nil
642 })
643
644 sourceErrCount := 0
645 sourceErr := cached.Func(func() ([]byte, string, error) {
646 sourceErrCount += 1
647 return nil, "", errors.New("source error")
648 })
649 lastSuccess := &cached.LastSuccess[[]byte]{}
650 lastSuccess.Store(sourceErr)
651 if _, _, err := lastSuccess.Get(); err == nil {
652 t.Fatalf("expected error, found none")
653 }
654 lastSuccess.Store(sourceData)
655 result, etag, err := lastSuccess.Get()
656 if err != nil {
657 t.Fatalf("unexpected error: %v", err)
658 }
659 if want := "source"; string(result) != want {
660 t.Fatalf("expected data = %v, got %v", want, string(result))
661 }
662 if want := "source"; etag != want {
663 t.Fatalf("expected etag = %v, got %v", want, etag)
664 }
665
666 lastSuccess.Store(sourceData)
667 result, etag, err = lastSuccess.Get()
668 if err != nil {
669 t.Fatalf("unexpected error: %v", err)
670 }
671 if want := "source"; string(result) != want {
672 t.Fatalf("expected data = %v, got %v", want, string(result))
673 }
674 if want := "source"; etag != want {
675 t.Fatalf("expected etag = %v, got %v", want, etag)
676 }
677
678 lastSuccess.Store(sourceErr)
679 result, etag, err = lastSuccess.Get()
680 if err != nil {
681 t.Fatalf("unexpected error: %v", err)
682 }
683 if want := "source"; string(result) != want {
684 t.Fatalf("expected data = %v, got %v", want, string(result))
685 }
686 if want := "source"; etag != want {
687 t.Fatalf("expected etag = %v, got %v", want, etag)
688 }
689 lastSuccess.Store(sourceData2)
690 result, etag, err = lastSuccess.Get()
691 if err != nil {
692 t.Fatalf("unexpected error: %v", err)
693 }
694 if want := "source2"; string(result) != want {
695 t.Fatalf("expected data = %v, got %v", want, string(result))
696 }
697 if want := "source2"; etag != want {
698 t.Fatalf("expected etag = %v, got %v", want, etag)
699 }
700 if sourceDataCount != 2 {
701 t.Fatalf("Expected sourceData function called twice, called: %v", sourceDataCount)
702 }
703 if sourceData2Count != 1 {
704 t.Fatalf("Expected sourceData2 function called once, called: %v", sourceData2Count)
705 }
706 if sourceErrCount != 2 {
707 t.Fatalf("Expected error source function called once, called: %v", sourceErrCount)
708 }
709 }
710
711 func TestLastSuccessEtag(t *testing.T) {
712 lastSuccess := &cached.LastSuccess[bool]{}
713 lastSuccess.Store(cached.Func(func() (bool, string, error) {
714 return false, "hash", nil
715 }))
716 lastSuccess.Store(cached.Static(true, "hash2"))
717 result, etag, _ := lastSuccess.Get()
718 if actual := etag; actual != "hash2" {
719 t.Fatalf(`expected "hash2", got %q`, actual)
720 }
721 if result != true {
722 t.Fatal(`expected "true", got "false"`)
723 }
724 }
725
726 func TestLastSuccessAlternateError(t *testing.T) {
727 sourceCount := 0
728 source := cached.Func(func() ([]byte, string, error) {
729 sourceCount += 1
730 if sourceCount%2 == 0 {
731 return nil, "", errors.New("source error")
732 } else {
733 return []byte("source"), "source", nil
734 }
735 })
736 lastSuccess := &cached.LastSuccess[[]byte]{}
737 lastSuccess.Store(source)
738 result, etag, err := lastSuccess.Get()
739 if err != nil {
740 t.Fatalf("unexpected error: %v", err)
741 }
742 if want := "source"; string(result) != want {
743 t.Fatalf("expected data = %v, got %v", want, string(result))
744 }
745 if want := "source"; etag != want {
746 t.Fatalf("expected etag = %v, got %v", want, etag)
747 }
748 result, etag, err = lastSuccess.Get()
749 if err != nil {
750 t.Fatalf("unexpected error: %v", err)
751 }
752 if want := "source"; string(result) != want {
753 t.Fatalf("expected data = %v, got %v", want, string(result))
754 }
755 if want := "source"; etag != want {
756 t.Fatalf("expected etag = %v, got %v", want, etag)
757 }
758 result, etag, err = lastSuccess.Get()
759 if err != nil {
760 t.Fatalf("unexpected error: %v", err)
761 }
762 if want := "source"; string(result) != want {
763 t.Fatalf("expected data = %v, got %v", want, string(result))
764 }
765 if want := "source"; etag != want {
766 t.Fatalf("expected etag = %v, got %v", want, etag)
767 }
768 result, etag, err = lastSuccess.Get()
769 if err != nil {
770 t.Fatalf("unexpected error: %v", err)
771 }
772 if want := "source"; string(result) != want {
773 t.Fatalf("expected data = %v, got %v", want, string(result))
774 }
775 if want := "source"; etag != want {
776 t.Fatalf("expected etag = %v, got %v", want, etag)
777 }
778 if sourceCount != 4 {
779 t.Fatalf("Expected sourceData function called 4x, called: %v", sourceCount)
780 }
781 }
782
783 func TestLastSuccessWithTransformer(t *testing.T) {
784 lastSuccess := &cached.LastSuccess[[]byte]{}
785 lastSuccess.Store(cached.Static([]byte("source"), "source"))
786 transformerCount := 0
787 transformed := cached.Transform[[]byte](func(value []byte, etag string, err error) ([]byte, string, error) {
788 transformerCount += 1
789 if err != nil {
790 return nil, "", err
791 }
792 return []byte("transformed " + string(value)), "transformed " + etag, nil
793 }, lastSuccess)
794 result, etag, err := transformed.Get()
795 if err != nil {
796 t.Fatalf("unexpected error: %v", err)
797 }
798 result, etag, err = transformed.Get()
799 if err != nil {
800 t.Fatalf("unexpected error: %v", err)
801 }
802 if want := "transformed source"; string(result) != want {
803 t.Fatalf("expected data = %v, got %v", want, string(result))
804 }
805 if want := "transformed source"; etag != want {
806 t.Fatalf("expected etag = %v, got %v", want, etag)
807 }
808
809 lastSuccess.Store(cached.Static([]byte("source"), "source"))
810 result, etag, err = transformed.Get()
811 if err != nil {
812 t.Fatalf("unexpected error: %v", err)
813 }
814 result, etag, err = transformed.Get()
815 if err != nil {
816 t.Fatalf("unexpected error: %v", err)
817 }
818 if want := "transformed source"; string(result) != want {
819 t.Fatalf("expected data = %v, got %v", want, string(result))
820 }
821 if want := "transformed source"; etag != want {
822 t.Fatalf("expected etag = %v, got %v", want, etag)
823 }
824
825 lastSuccess.Store(cached.Result[[]byte]{Err: errors.New("source error")})
826 result, etag, err = transformed.Get()
827 if err != nil {
828 t.Fatalf("unexpected error: %v", err)
829 }
830 result, etag, err = transformed.Get()
831 if err != nil {
832 t.Fatalf("unexpected error: %v", err)
833 }
834 if want := "transformed source"; string(result) != want {
835 t.Fatalf("expected data = %v, got %v", want, string(result))
836 }
837 if want := "transformed source"; etag != want {
838 t.Fatalf("expected etag = %v, got %v", want, etag)
839 }
840
841 if transformerCount != 1 {
842 t.Fatalf("Expected transformer function called once, called: %v", transformerCount)
843 }
844 }
845
846
847
848 func Example() {
849
850
851 mergeJson := &cached.LastSuccess[[]byte]{}
852
853 one := cached.Once(cached.Func(func() ([]byte, string, error) {
854
855 return []byte("one"), "one", nil
856 }))
857 two := cached.Func(func() ([]byte, string, error) {
858
859 return []byte("two"), "two", nil
860 })
861
862 three := cached.Static([]byte("three"), "three")
863
864
865
866
867 lastSuccess := &cached.LastSuccess[[]byte]{}
868 lastSuccess.Store(cached.Static([]byte("four"), "four"))
869
870 merger := func(results map[string]cached.Result[[]byte]) ([]byte, string, error) {
871 var out = []json.RawMessage{}
872 var resultEtag string
873 for _, result := range results {
874 if result.Err != nil {
875 return nil, "", result.Err
876 }
877 resultEtag += result.Etag
878 out = append(out, result.Value)
879 }
880 data, err := json.Marshal(out)
881 if err != nil {
882 return nil, "", err
883 }
884 return data, resultEtag, nil
885 }
886
887 mergeJson.Store(cached.Merge(merger, map[string]cached.Value[[]byte]{
888 "one": one,
889 "two": two,
890 "three": three,
891 "replaceable": lastSuccess,
892 }))
893
894
895
896 indented := cached.Transform[[]byte](func(js []byte, etag string, err error) ([]byte, string, error) {
897
898
899 if err != nil {
900 return nil, "", err
901 }
902 var out bytes.Buffer
903 json.Indent(&out, js, "", "\t")
904 return out.Bytes(), etag, nil
905 }, mergeJson)
906
907
908 go func() {
909 for {
910 if _, _, err := indented.Get(); err != nil {
911 panic(fmt.Errorf("invalid error: %v", err))
912 }
913 }
914 }()
915
916 failure := cached.Result[[]byte]{Err: errors.New("Invalid cache!")}
917
918 mergeJson.Store(cached.Merge(merger, map[string]cached.Value[[]byte]{
919 "one": one,
920 "two": two,
921 "three": three,
922 "replaceable": lastSuccess,
923 "failure": failure,
924 }))
925
926
927 lastSuccess.Store(cached.Static([]byte("five"), "five"))
928
929
930 mergeJson.Store(cached.Merge(merger, map[string]cached.Value[[]byte]{
931 "one": one,
932 "two": two,
933 "replaceable": lastSuccess,
934 }))
935 }
936
937 func TestListMerger(t *testing.T) {
938 source1Count := 0
939 source1 := cached.Func(func() ([]byte, string, error) {
940 source1Count += 1
941 return []byte("source1"), "source1", nil
942 })
943 source2Count := 0
944 source2 := cached.Func(func() ([]byte, string, error) {
945 source2Count += 1
946 return []byte("source2"), "source2", nil
947 })
948 mergerCount := 0
949 merger := cached.MergeList(func(results []cached.Result[[]byte]) ([]byte, string, error) {
950 mergerCount += 1
951 d := []string{}
952 e := []string{}
953 for _, result := range results {
954 if result.Err != nil {
955 return nil, "", result.Err
956 }
957 d = append(d, string(result.Value))
958 e = append(e, result.Etag)
959 }
960 return []byte("merged " + strings.Join(d, " and ")), "merged " + strings.Join(e, " and "), nil
961 }, []cached.Value[[]byte]{
962 source1, source2,
963 })
964 if _, _, err := merger.Get(); err != nil {
965 t.Fatalf("unexpected error: %v", err)
966 }
967 result, etag, err := merger.Get()
968 if err != nil {
969 t.Fatalf("unexpected error: %v", err)
970 }
971 if want := "merged source1 and source2"; string(result) != want {
972 t.Fatalf("expected data = %v, got %v", want, string(result))
973 }
974 if want := "merged source1 and source2"; etag != want {
975 t.Fatalf("expected etag = %v, got %v", want, etag)
976 }
977
978 if source1Count != 2 {
979 t.Fatalf("Expected source function called twice, called: %v", source1Count)
980 }
981 if source2Count != 2 {
982 t.Fatalf("Expected source function called twice, called: %v", source2Count)
983 }
984 if mergerCount != 1 {
985 t.Fatalf("Expected merger function called once, called: %v", mergerCount)
986 }
987 }
988
989 func TestMergeListSourceError(t *testing.T) {
990 source1Count := 0
991 source1 := cached.Func(func() ([]byte, string, error) {
992 source1Count += 1
993 return nil, "", errors.New("source1 error")
994 })
995 source2Count := 0
996 source2 := cached.Func(func() ([]byte, string, error) {
997 source2Count += 1
998 return []byte("source2"), "source2", nil
999 })
1000 mergerCount := 0
1001 merger := cached.MergeList(func(results []cached.Result[[]byte]) ([]byte, string, error) {
1002 mergerCount += 1
1003 d := []string{}
1004 e := []string{}
1005 for _, result := range results {
1006 if result.Err != nil {
1007 return nil, "", result.Err
1008 }
1009 d = append(d, string(result.Value))
1010 e = append(e, result.Etag)
1011 }
1012 return []byte("merged " + strings.Join(d, " and ")), "merged " + strings.Join(e, " and "), nil
1013 }, []cached.Value[[]byte]{
1014 source1, source2,
1015 })
1016 if _, _, err := merger.Get(); err == nil {
1017 t.Fatalf("expected error, none found")
1018 }
1019 if _, _, err := merger.Get(); err == nil {
1020 t.Fatalf("expected error, none found")
1021 }
1022 if source1Count != 2 {
1023 t.Fatalf("Expected source function called twice, called: %v", source1Count)
1024 }
1025 if source2Count != 2 {
1026 t.Fatalf("Expected source function called twice, called: %v", source2Count)
1027 }
1028 if mergerCount != 2 {
1029 t.Fatalf("Expected merger function called twice, called: %v", mergerCount)
1030 }
1031 }
1032
1033 func TestMergeListAlternateSourceError(t *testing.T) {
1034 source1Count := 0
1035 source1 := cached.Func(func() ([]byte, string, error) {
1036 source1Count += 1
1037 if source1Count%2 == 0 {
1038 return nil, "", errors.New("source1 error")
1039 } else {
1040 return []byte("source1"), "source1", nil
1041 }
1042 })
1043 source2Count := 0
1044 source2 := cached.Func(func() ([]byte, string, error) {
1045 source2Count += 1
1046 return []byte("source2"), "source2", nil
1047 })
1048 mergerCount := 0
1049 merger := cached.MergeList(func(results []cached.Result[[]byte]) ([]byte, string, error) {
1050 mergerCount += 1
1051 d := []string{}
1052 e := []string{}
1053 for _, result := range results {
1054 if result.Err != nil {
1055 return nil, "", result.Err
1056 }
1057 d = append(d, string(result.Value))
1058 e = append(e, result.Etag)
1059 }
1060 return []byte("merged " + strings.Join(d, " and ")), "merged " + strings.Join(e, " and "), nil
1061 }, []cached.Value[[]byte]{
1062 source1, source2,
1063 })
1064 result, etag, err := merger.Get()
1065 if err != nil {
1066 t.Fatalf("unexpected error: %v", err)
1067 }
1068 if want := "merged source1 and source2"; string(result) != want {
1069 t.Fatalf("expected data = %v, got %v", want, string(result))
1070 }
1071 if want := "merged source1 and source2"; etag != want {
1072 t.Fatalf("expected etag = %v, got %v", want, etag)
1073 }
1074 if _, _, err := merger.Get(); err == nil {
1075 t.Fatalf("expected error, none found")
1076 }
1077 result, etag, err = merger.Get()
1078 if err != nil {
1079 t.Fatalf("unexpected error: %v", err)
1080 }
1081 if want := "merged source1 and source2"; string(result) != want {
1082 t.Fatalf("expected data = %v, got %v", want, string(result))
1083 }
1084 if want := "merged source1 and source2"; etag != want {
1085 t.Fatalf("expected etag = %v, got %v", want, etag)
1086 }
1087 if _, _, err := merger.Get(); err == nil {
1088 t.Fatalf("expected error, none found")
1089 }
1090 if source1Count != 4 {
1091 t.Fatalf("Expected source function called 4x, called: %v", source1Count)
1092 }
1093 if source2Count != 4 {
1094 t.Fatalf("Expected source function called 4x, called: %v", source2Count)
1095 }
1096 if mergerCount != 4 {
1097 t.Fatalf("Expected merger function called 4x, called: %v", mergerCount)
1098 }
1099 }
1100
1101 func TestListDAG(t *testing.T) {
1102 source := cached.Func(func() ([]byte, string, error) {
1103 return []byte("source"), "source", nil
1104 })
1105 transformer1 := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
1106 if err != nil {
1107 return nil, "", err
1108 }
1109 return []byte("transformed1 " + string(value)), "transformed1 " + etag, nil
1110 }, source)
1111 transformer2 := cached.Transform(func(value []byte, etag string, err error) ([]byte, string, error) {
1112 if err != nil {
1113 return nil, "", err
1114 }
1115 return []byte("transformed2 " + string(value)), "transformed2 " + etag, nil
1116 }, source)
1117 merger := cached.MergeList(func(results []cached.Result[[]byte]) ([]byte, string, error) {
1118 d := []string{}
1119 e := []string{}
1120 for _, result := range results {
1121 if result.Err != nil {
1122 return nil, "", result.Err
1123 }
1124 d = append(d, string(result.Value))
1125 e = append(e, result.Etag)
1126 }
1127 return []byte("merged " + strings.Join(d, " and ")), "merged " + strings.Join(e, " and "), nil
1128 }, []cached.Value[[]byte]{
1129 transformer1, transformer2,
1130 })
1131 result, etag, err := merger.Get()
1132 if err != nil {
1133 t.Fatalf("Unexpected error: %v", err)
1134 }
1135 if want := "merged transformed1 source and transformed2 source"; string(result) != want {
1136 t.Fatalf("expected data = %v, got %v", want, string(result))
1137 }
1138 if want := "merged transformed1 source and transformed2 source"; etag != want {
1139 t.Fatalf("expected etag = %v, got %v", want, etag)
1140 }
1141 }
1142
1143 func randomString(length uint) string {
1144 bytes := make([]byte, 6)
1145 rand.Read(bytes)
1146 return string(bytes)
1147
1148 }
1149
1150 func NewRandomSource() cached.Value[int64] {
1151 return cached.Once(cached.Func(func() (int64, string, error) {
1152 bytes := make([]byte, 6)
1153 rand.Read(bytes)
1154 return rand.Int63(), randomString(10), nil
1155 }))
1156 }
1157
1158 func repeatedGet(data cached.Value[int64], end time.Time, wg *sync.WaitGroup) {
1159 for time.Now().Before(end) {
1160 _, _, _ = data.Get()
1161 }
1162 wg.Done()
1163 }
1164
1165 func TestThreadSafe(t *testing.T) {
1166 end := time.Now().Add(time.Second)
1167 wg := sync.WaitGroup{}
1168 static := NewRandomSource()
1169 wg.Add(1)
1170 go repeatedGet(static, end, &wg)
1171 result := cached.Static(rand.Int63(), randomString(10))
1172 wg.Add(1)
1173 go repeatedGet(result, end, &wg)
1174 replaceable := &cached.LastSuccess[int64]{}
1175 replaceable.Store(NewRandomSource())
1176 wg.Add(1)
1177 go repeatedGet(replaceable, end, &wg)
1178 wg.Add(1)
1179 go func(r cached.Replaceable[int64], end time.Time, wg *sync.WaitGroup) {
1180 for time.Now().Before(end) {
1181 r.Store(NewRandomSource())
1182 }
1183 wg.Done()
1184 }(replaceable, end, &wg)
1185 merger := cached.Merge(func(results map[string]cached.Result[int64]) (int64, string, error) {
1186 sum := int64(0)
1187 for _, result := range results {
1188 sum += result.Value
1189 }
1190 return sum, randomString(10), nil
1191 }, map[string]cached.Value[int64]{
1192 "one": NewRandomSource(),
1193 "two": NewRandomSource(),
1194 })
1195 wg.Add(1)
1196 go repeatedGet(merger, end, &wg)
1197 transformer := cached.Transform(func(value int64, etag string, err error) (int64, string, error) {
1198 return value + 5, randomString(10), nil
1199 }, NewRandomSource())
1200 wg.Add(1)
1201 go repeatedGet(transformer, end, &wg)
1202
1203 listmerger := cached.MergeList(func(results []cached.Result[int64]) (int64, string, error) {
1204 sum := int64(0)
1205 for i := range results {
1206 sum += results[i].Value
1207 }
1208 return sum, randomString(10), nil
1209 }, []cached.Value[int64]{static, result, replaceable, merger, transformer})
1210 wg.Add(1)
1211 go repeatedGet(listmerger, end, &wg)
1212
1213 wg.Wait()
1214 }
1215
View as plain text