1 package testutil_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/cybertec-postgresql/pgwatch/v3/api/pb" 8 "github.com/cybertec-postgresql/pgwatch/v3/internal/metrics" 9 "github.com/cybertec-postgresql/pgwatch/v3/internal/sources" 10 "github.com/cybertec-postgresql/pgwatch/v3/internal/testutil" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 "google.golang.org/protobuf/types/known/structpb" 14 ) 15 16 func TestReceiver_UpdateMeasurements(t *testing.T) { 17 receiver := &testutil.Receiver{} 18 ctx := context.Background() 19 20 t.Run("valid message", func(t *testing.T) { 21 data, err := structpb.NewStruct(map[string]any{"test": "value"}) 22 require.NoError(t, err) 23 msg := &pb.MeasurementEnvelope{ 24 DBName: "Db", 25 Data: []*structpb.Struct{data}, 26 } 27 reply, err := receiver.UpdateMeasurements(ctx, msg) 28 assert.NoError(t, err) 29 assert.NotNil(t, reply) 30 }) 31 32 t.Run("empty data", func(t *testing.T) { 33 msg := &pb.MeasurementEnvelope{ 34 DBName: "Db", 35 Data: []*structpb.Struct{}, 36 } 37 reply, err := receiver.UpdateMeasurements(ctx, msg) 38 assert.Error(t, err) 39 assert.Nil(t, reply) 40 assert.EqualError(t, err, "empty message") 41 }) 42 43 t.Run("invalid db name", func(t *testing.T) { 44 data, err := structpb.NewStruct(map[string]any{"test": "value"}) 45 require.NoError(t, err) 46 msg := &pb.MeasurementEnvelope{ 47 DBName: "WrongDb", 48 Data: []*structpb.Struct{data}, 49 } 50 reply, err := receiver.UpdateMeasurements(ctx, msg) 51 assert.Error(t, err) 52 assert.Nil(t, reply) 53 assert.EqualError(t, err, "invalid message") 54 }) 55 } 56 57 func TestReceiver_SyncMetric(t *testing.T) { 58 receiver := &testutil.Receiver{} 59 ctx := context.Background() 60 61 t.Run("valid sync request", func(t *testing.T) { 62 syncReq := &pb.SyncReq{ 63 Operation: pb.SyncOp_AddOp, 64 } 65 reply, err := receiver.SyncMetric(ctx, syncReq) 66 assert.NoError(t, err) 67 assert.NotNil(t, reply) 68 }) 69 70 t.Run("nil sync request", func(t *testing.T) { 71 reply, err := receiver.SyncMetric(ctx, nil) 72 assert.Error(t, err) 73 assert.Nil(t, reply) 74 assert.EqualError(t, err, "nil sync request") 75 }) 76 77 t.Run("invalid operation", func(t *testing.T) { 78 syncReq := &pb.SyncReq{ 79 Operation: pb.SyncOp_InvalidOp, 80 } 81 reply, err := receiver.SyncMetric(ctx, syncReq) 82 assert.Error(t, err) 83 assert.Nil(t, reply) 84 assert.EqualError(t, err, "invalid sync request") 85 }) 86 } 87 88 func TestReceiver_DefineMetrics(t *testing.T) { 89 receiver := &testutil.Receiver{} 90 ctx := context.Background() 91 92 t.Run("valid metrics struct", func(t *testing.T) { 93 metricsStruct, err := structpb.NewStruct(map[string]any{ 94 "metric1": "value1", 95 }) 96 assert.NoError(t, err) 97 98 reply, err := receiver.DefineMetrics(ctx, metricsStruct) 99 assert.NoError(t, err) 100 assert.NotNil(t, reply) 101 assert.Equal(t, "metrics defined successfully", reply.Logmsg) 102 }) 103 104 t.Run("nil metrics struct", func(t *testing.T) { 105 reply, err := receiver.DefineMetrics(ctx, nil) 106 assert.Error(t, err) 107 assert.Nil(t, reply) 108 assert.EqualError(t, err, "nil metrics struct") 109 }) 110 111 t.Run("empty metrics struct", func(t *testing.T) { 112 metricsStruct := &structpb.Struct{} 113 reply, err := receiver.DefineMetrics(ctx, metricsStruct) 114 assert.Error(t, err) 115 assert.Nil(t, reply) 116 assert.EqualError(t, err, "empty metrics struct") 117 }) 118 } 119 120 func TestMockMetricsReaderWriter(t *testing.T) { 121 testData := &metrics.Metrics{ 122 MetricDefs: map[string]metrics.Metric{"foo": {Description: "bar"}}, 123 PresetDefs: map[string]metrics.Preset{"foo": {Description: "bar"}}, 124 } 125 called := false 126 127 mock := testutil.MockMetricsReaderWriter{ 128 GetMetricsFunc: func() (*metrics.Metrics, error) { 129 called = true 130 return testData, nil 131 }, 132 WriteMetricsFunc: func(*metrics.Metrics) error { 133 called = true 134 return nil 135 }, 136 UpdateMetricFunc: func(string, metrics.Metric) error { 137 called = true 138 return nil 139 }, 140 DeleteMetricFunc: func(string) error { 141 called = true 142 return nil 143 }, 144 CreateMetricFunc: func(string, metrics.Metric) error { 145 called = true 146 return nil 147 }, 148 CreatePresetFunc: func(string, metrics.Preset) error { 149 called = true 150 return nil 151 }, 152 UpdatePresetFunc: func(string, metrics.Preset) error { 153 called = true 154 return nil 155 }, 156 DeletePresetFunc: func(string) error { 157 called = true 158 return nil 159 }, 160 } 161 162 t.Run("GetMetrics", func(t *testing.T) { 163 called = false 164 metrics, err := mock.GetMetrics() 165 assert.NoError(t, err) 166 assert.Equal(t, true, called) 167 assert.Equal(t, testData, metrics) 168 }) 169 170 t.Run("WriteMetrics", func(t *testing.T) { 171 called = false 172 err := mock.WriteMetrics(testData) 173 assert.NoError(t, err) 174 assert.Equal(t, true, called) 175 }) 176 177 t.Run("UpdateMetric", func(t *testing.T) { 178 called = false 179 err := mock.UpdateMetric("foo", testData.MetricDefs["foo"]) 180 assert.NoError(t, err) 181 assert.Equal(t, true, called) 182 }) 183 184 t.Run("DeleteMetric", func(t *testing.T) { 185 called = false 186 err := mock.DeleteMetric("foo") 187 assert.NoError(t, err) 188 assert.Equal(t, true, called) 189 }) 190 191 t.Run("CreateMetric", func(t *testing.T) { 192 called = false 193 err := mock.CreateMetric("foo", testData.MetricDefs["foo"]) 194 assert.NoError(t, err) 195 assert.Equal(t, true, called) 196 }) 197 198 t.Run("CreatePreset", func(t *testing.T) { 199 called = false 200 err := mock.CreatePreset("foo", testData.PresetDefs["foo"]) 201 assert.NoError(t, err) 202 assert.Equal(t, true, called) 203 }) 204 205 t.Run("UpdatePreset", func(t *testing.T) { 206 called = false 207 err := mock.UpdatePreset("foo", testData.PresetDefs["foo"]) 208 assert.NoError(t, err) 209 assert.Equal(t, true, called) 210 }) 211 212 t.Run("DeletePreset", func(t *testing.T) { 213 called = false 214 err := mock.DeletePreset("foo") 215 assert.NoError(t, err) 216 assert.Equal(t, true, called) 217 }) 218 } 219 220 func TestMockSourcesReaderWriter(t *testing.T) { 221 testData := sources.Sources{{Name: "foo", ConnStr: "postgres://foo@bar"}} 222 called := false 223 mock := testutil.MockSourcesReaderWriter{ 224 GetSourcesFunc: func() (sources.Sources, error) { 225 called = true 226 return testData, nil 227 }, 228 WriteSourcesFunc: func(sources.Sources) error { 229 called = true 230 return nil 231 }, 232 UpdateSourceFunc: func(sources.Source) error { 233 called = true 234 return nil 235 }, 236 CreateSourceFunc: func(sources.Source) error { 237 called = true 238 return nil 239 }, 240 DeleteSourceFunc: func(string) error { 241 called = true 242 return nil 243 }, 244 } 245 246 t.Run("GetSources", func(t *testing.T) { 247 called = false 248 sources, err := mock.GetSources() 249 assert.NoError(t, err) 250 assert.Equal(t, true, called) 251 assert.Equal(t, testData, sources) 252 }) 253 254 t.Run("WriteSources", func(t *testing.T) { 255 called = false 256 err := mock.WriteSources(testData) 257 assert.NoError(t, err) 258 assert.Equal(t, true, called) 259 }) 260 261 t.Run("UpdateSource", func(t *testing.T) { 262 called = false 263 err := mock.UpdateSource(testData[0]) 264 assert.NoError(t, err) 265 assert.Equal(t, true, called) 266 }) 267 268 t.Run("DeleteSource", func(t *testing.T) { 269 called = false 270 err := mock.DeleteSource("foo") 271 assert.NoError(t, err) 272 assert.Equal(t, true, called) 273 }) 274 275 t.Run("CreateSource", func(t *testing.T) { 276 called = false 277 err := mock.CreateSource(testData[0]) 278 assert.NoError(t, err) 279 assert.Equal(t, true, called) 280 }) 281 }