engine_test.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package template // import "miniflux.app/v2/internal/template"
  4. import (
  5. "bytes"
  6. "sync"
  7. "testing"
  8. )
  9. // TestRenderConcurrency renders the same template concurrently in different
  10. // languages. Because Render binds per-request, language-specific functions
  11. // ("t", "plural", "elapsed") onto the template, doing so on a shared template
  12. // while other requests execute it corrupts the output: a request can be served
  13. // another request's language. Each concurrent render must match the output of
  14. // the equivalent sequential render for its language.
  15. func TestRenderConcurrency(t *testing.T) {
  16. engine := NewEngine("")
  17. engine.ParseTemplates()
  18. languages := []string{"en_US", "fr_FR", "de_DE", "es_ES", "pt_BR", "ru_RU", "zh_CN", "it_IT"}
  19. newData := func(language string) map[string]any {
  20. return map[string]any{"language": language, "theme": "system_serif"}
  21. }
  22. // Establish the expected output for each language sequentially.
  23. expected := make(map[string][]byte, len(languages))
  24. for _, language := range languages {
  25. expected[language] = engine.Render("offline.html", newData(language))
  26. }
  27. const iterations = 300
  28. var wg sync.WaitGroup
  29. var mu sync.Mutex
  30. mismatches := make(map[string]int)
  31. for i := 0; i < iterations; i++ {
  32. language := languages[i%len(languages)]
  33. wg.Add(1)
  34. go func(language string) {
  35. defer wg.Done()
  36. got := engine.Render("offline.html", newData(language))
  37. if !bytes.Equal(got, expected[language]) {
  38. mu.Lock()
  39. mismatches[language]++
  40. mu.Unlock()
  41. }
  42. }(language)
  43. }
  44. wg.Wait()
  45. if len(mismatches) > 0 {
  46. total := 0
  47. for _, n := range mismatches {
  48. total += n
  49. }
  50. t.Fatalf("concurrent Render produced wrong output for %d/%d requests (wrong-language translations); per-language mismatches: %v", total, iterations, mismatches)
  51. }
  52. }