master
go 115 lines 3 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package metricsaudit
4
5 import (
6 "encoding/json"
7 "os"
8 "path/filepath"
9 "testing"
10 "time"
11
12 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
13 )
14
15 func TestAuditorSeparatesSameJobNameAcrossModules(t *testing.T) {
16 da := New()
17
18 da.RegisterJob("shared", "modA", "")
19 da.RegisterJob("shared", "modB", "")
20
21 chartsA := testCharts("chart_a", "ctx_a", "dim_a")
22 chartsB := testCharts("chart_b", "ctx_b", "dim_b")
23 da.RecordJobStructure("shared", "modA", &chartsA)
24 da.RecordJobStructure("shared", "modB", &chartsB)
25
26 da.RecordCollection("shared", "modA", map[string]int64{"dim_a": 1})
27 da.RecordCollection("shared", "modB", map[string]int64{"dim_b": 2})
28
29 idA := newJobID("modA", "shared")
30 idB := newJobID("modB", "shared")
31
32 if got := len(da.jobs); got != 2 {
33 t.Fatalf("expected 2 jobs, got %d", got)
34 }
35 if da.jobs[idA] == nil || da.jobs[idB] == nil {
36 t.Fatalf("expected both module-scoped jobs to exist: %+v", da.jobs)
37 }
38 if da.jobs[idA].CollectionCount != 1 || da.jobs[idB].CollectionCount != 1 {
39 t.Fatalf("expected per-module collection counts to be isolated, got %d and %d",
40 da.jobs[idA].CollectionCount, da.jobs[idB].CollectionCount)
41 }
42 if !da.jobs[idA].AllSeenMetrics["dim_a"] {
43 t.Fatalf("expected modA metrics to include dim_a")
44 }
45 if !da.jobs[idB].AllSeenMetrics["dim_b"] {
46 t.Fatalf("expected modB metrics to include dim_b")
47 }
48 }
49
50 func TestAuditorOnCompleteAfterAllRegisteredJobsCollected(t *testing.T) {
51 da := New()
52 baseDir := t.TempDir()
53
54 done := make(chan struct{}, 1)
55 da.EnableDataCapture(baseDir, func() {
56 select {
57 case done <- struct{}{}:
58 default:
59 }
60 })
61
62 job1Dir := filepath.Join(baseDir, "mod", "job1")
63 job2Dir := filepath.Join(baseDir, "mod", "job2")
64 da.RegisterJob("job1", "mod", job1Dir)
65 da.RegisterJob("job2", "mod", job2Dir)
66
67 charts1 := testCharts("chart1", "ctx1", "dim1")
68 charts2 := testCharts("chart2", "ctx2", "dim2")
69 da.RecordJobStructure("job1", "mod", &charts1)
70 da.RecordJobStructure("job2", "mod", &charts2)
71
72 da.RecordCollection("job1", "mod", map[string]int64{"dim1": 10})
73 select {
74 case <-done:
75 t.Fatalf("onComplete fired before all registered jobs collected")
76 default:
77 }
78
79 da.RecordCollection("job2", "mod", map[string]int64{"dim2": 20})
80 select {
81 case <-done:
82 case <-time.After(2 * time.Second):
83 t.Fatalf("timed out waiting for onComplete callback")
84 }
85
86 if !da.flushWriteQueue(2 * time.Second) {
87 t.Fatalf("failed to flush write queue")
88 }
89
90 manifestPath := filepath.Join(baseDir, "manifest.json")
91 data, err := os.ReadFile(manifestPath)
92 if err != nil {
93 t.Fatalf("read manifest: %v", err)
94 }
95
96 var manifest manifestPayload
97 if err := json.Unmarshal(data, &manifest); err != nil {
98 t.Fatalf("decode manifest: %v", err)
99 }
100 if got := len(manifest.Jobs); got != 2 {
101 t.Fatalf("expected 2 jobs in manifest, got %d", got)
102 }
103 }
104
105 func testCharts(chartID, context, dimID string) collectorapi.Charts {
106 return collectorapi.Charts{
107 {
108 ID: chartID,
109 Ctx: context,
110 Dims: collectorapi.Dims{
111 {ID: dimID},
112 },
113 },
114 }
115 }