Skip to content

Commit fc1c375

Browse files
[*] improve tests for PostgresMetricReaderWriter (#1221)
* Tests for /internal/metrics/postgres_test.go, fix #1099 * add `newTestReaderWriter` helper and move sub-tests to `TestMetricsToPostgres` --------- Co-authored-by: Pavlo Golub <[email protected]>
1 parent 8328efd commit fc1c375

2 files changed

Lines changed: 113 additions & 50 deletions

File tree

internal/metrics/postgres.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
143143
if err != nil {
144144
// Check for unique constraint violation using PostgreSQL error code
145145
var pgErr *pgconn.PgError
146-
if errors.As(err, &pgErr) && pgErr.SQLState() == "23505" {
146+
if errors.As(err, &pgErr) && pgErr.Code == "23505" {
147147
return ErrMetricExists
148148
}
149149
}

internal/metrics/postgres_test.go

Lines changed: 112 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/cybertec-postgresql/pgwatch/v5/internal/log"
88
"github.com/cybertec-postgresql/pgwatch/v5/internal/metrics"
9+
"github.com/jackc/pgx/v5/pgconn"
910
"github.com/pashagolub/pgxmock/v4"
1011
"github.com/stretchr/testify/assert"
1112
)
@@ -170,17 +171,24 @@ func TestNewPostgresMetricReaderWriterConn(t *testing.T) {
170171
})
171172
}
172173

173-
func TestMetricsToPostgres(t *testing.T) {
174-
a := assert.New(t)
174+
func newTestReaderWriter(t *testing.T) (pgxmock.PgxPoolIface, metrics.ReaderWriter) {
175+
t.Helper()
175176
conn, err := pgxmock.NewPool()
176-
a.NoError(err)
177-
178-
conn.ExpectQuery(`SELECT EXISTS`).WithArgs("pgwatch").WillReturnRows(pgxmock.NewRows([]string{"exists"}).AddRow(true))
177+
if err != nil {
178+
t.Fatalf("pgxmock.NewPool: %v", err)
179+
}
180+
conn.ExpectQuery(`SELECT EXISTS`).WithArgs("pgwatch").
181+
WillReturnRows(pgxmock.NewRows([]string{"exists"}).AddRow(true))
179182
conn.ExpectPing()
183+
rw, err := metrics.NewPostgresMetricReaderWriterConn(ctx, conn)
184+
if err != nil {
185+
t.Fatalf("NewPostgresMetricReaderWriterConn: %v", err)
186+
}
187+
return conn, rw
188+
}
180189

181-
readerWriter, err := metrics.NewPostgresMetricReaderWriterConn(ctx, conn)
182-
a.NoError(err)
183-
a.NotNil(readerWriter)
190+
func TestMetricsToPostgres(t *testing.T) {
191+
conn, rw := newTestReaderWriter(t)
184192

185193
metricsRows := func() *pgxmock.Rows {
186194
return pgxmock.NewRows([]string{"name", "sqls", "init_sql", "description", "node_status", "gauges", "is_instance_level", "storage_name"}).
@@ -191,85 +199,140 @@ func TestMetricsToPostgres(t *testing.T) {
191199
AddRow("test", "desc", map[string]float64{"metric": 30})
192200
}
193201

194-
t.Run("GetMetrics", func(*testing.T) {
202+
t.Run("GetMetrics", func(t *testing.T) {
195203
conn.ExpectQuery(`SELECT.+FROM.+metric`).WillReturnRows(metricsRows())
196204
conn.ExpectQuery(`SELECT.+FROM.+preset`).WillReturnRows(presetRows())
197-
198-
m, err := readerWriter.GetMetrics()
199-
a.NoError(err)
200-
a.Len(m.MetricDefs, 1)
205+
m, err := rw.GetMetrics()
206+
assert.NoError(t, err)
207+
assert.Len(t, m.MetricDefs, 1)
201208
})
202209

203-
t.Run("GetMetricsFail", func(*testing.T) {
210+
t.Run("GetMetricsFail", func(t *testing.T) {
204211
conn.ExpectQuery(`SELECT.+FROM.+metric`).WillReturnError(assert.AnError)
205-
_, err = readerWriter.GetMetrics()
206-
a.Error(err)
212+
_, err := rw.GetMetrics()
213+
assert.Error(t, err)
207214
})
208215

209-
t.Run("GetPresetsFail", func(*testing.T) {
216+
t.Run("GetPresetsFail", func(t *testing.T) {
210217
conn.ExpectQuery(`SELECT.+FROM.+metric`).WillReturnRows(metricsRows())
211218
conn.ExpectQuery(`SELECT.+FROM.+preset`).WillReturnError(assert.AnError)
212-
_, err = readerWriter.GetMetrics()
213-
a.Error(err)
219+
_, err := rw.GetMetrics()
220+
assert.Error(t, err)
214221
})
215222

216-
t.Run("GetMetricsScanFail", func(*testing.T) {
223+
t.Run("GetMetricsScanFail", func(t *testing.T) {
217224
conn.ExpectQuery(`SELECT.+FROM.+metric`).WillReturnRows(metricsRows().RowError(0, assert.AnError))
218-
_, err = readerWriter.GetMetrics()
219-
a.Error(err)
225+
_, err := rw.GetMetrics()
226+
assert.Error(t, err)
220227
})
221228

222-
t.Run("GetPresetsScanFail", func(*testing.T) {
229+
t.Run("GetPresetsScanFail", func(t *testing.T) {
223230
conn.ExpectQuery(`SELECT.+FROM.+metric`).WillReturnRows(metricsRows())
224231
conn.ExpectQuery(`SELECT.+FROM.+preset`).WillReturnRows(presetRows().RowError(0, assert.AnError))
225-
_, err = readerWriter.GetMetrics()
226-
a.Error(err)
232+
_, err := rw.GetMetrics()
233+
assert.Error(t, err)
227234
})
228235

229-
t.Run("WriteMetrics", func(*testing.T) {
236+
t.Run("WriteMetrics", func(t *testing.T) {
230237
conn.ExpectBegin().WillReturnError(assert.AnError)
231-
err = readerWriter.WriteMetrics(&metrics.Metrics{})
232-
a.Error(err)
238+
assert.Error(t, rw.WriteMetrics(&metrics.Metrics{}))
233239
})
234240

235-
t.Run("DeleteMetric", func(*testing.T) {
241+
t.Run("DeleteMetric", func(t *testing.T) {
236242
conn.ExpectExec(`DELETE.+metric`).WithArgs("test").WillReturnResult(pgxmock.NewResult("DELETE", 1))
237-
err = readerWriter.DeleteMetric("test")
238-
a.NoError(err)
243+
assert.NoError(t, rw.DeleteMetric("test"))
239244
})
240245

241-
t.Run("UpdateMetric", func(*testing.T) {
246+
t.Run("UpdateMetric", func(t *testing.T) {
242247
conn.ExpectExec(`INSERT.+metric`).WithArgs(AnyArgs(8)...).WillReturnResult(pgxmock.NewResult("UPDATE", 1))
243-
err = readerWriter.UpdateMetric("test", metrics.Metric{})
244-
a.NoError(err)
248+
assert.NoError(t, rw.UpdateMetric("test", metrics.Metric{}))
245249
})
246250

247-
t.Run("FailUpdateMetric", func(*testing.T) {
251+
t.Run("FailUpdateMetric", func(t *testing.T) {
248252
conn.ExpectExec(`INSERT.+metric`).WithArgs(AnyArgs(8)...).WillReturnResult(pgxmock.NewResult("UPDATE", 0))
249-
err = readerWriter.UpdateMetric("test", metrics.Metric{})
250-
a.ErrorIs(err, metrics.ErrMetricNotFound)
253+
assert.ErrorIs(t, rw.UpdateMetric("test", metrics.Metric{}), metrics.ErrMetricNotFound)
251254
})
252255

253-
t.Run("DeletePreset", func(*testing.T) {
256+
t.Run("DeletePreset", func(t *testing.T) {
254257
conn.ExpectExec(`DELETE.+preset`).WithArgs("test").WillReturnResult(pgxmock.NewResult("DELETE", 1))
255-
err = readerWriter.DeletePreset("test")
256-
a.NoError(err)
258+
assert.NoError(t, rw.DeletePreset("test"))
257259
})
258260

259-
t.Run("UpdatePreset", func(*testing.T) {
261+
t.Run("UpdatePreset", func(t *testing.T) {
260262
conn.ExpectExec(`INSERT.+preset`).WithArgs(AnyArgs(3)...).WillReturnResult(pgxmock.NewResult("INSERT", 1))
261-
err = readerWriter.UpdatePreset("test", metrics.Preset{})
262-
a.NoError(err)
263+
assert.NoError(t, rw.UpdatePreset("test", metrics.Preset{}))
263264
})
264265

265-
t.Run("FailUpdatePreset", func(*testing.T) {
266+
t.Run("FailUpdatePreset", func(t *testing.T) {
266267
conn.ExpectExec(`INSERT.+preset`).WithArgs(AnyArgs(3)...).WillReturnResult(pgxmock.NewResult("INSERT", 0))
267-
err = readerWriter.UpdatePreset("test", metrics.Preset{})
268-
a.ErrorIs(err, metrics.ErrPresetNotFound)
268+
assert.ErrorIs(t, rw.UpdatePreset("test", metrics.Preset{}), metrics.ErrPresetNotFound)
269+
})
270+
271+
t.Run("DeleteMetricError", func(t *testing.T) {
272+
conn.ExpectExec(`DELETE.+metric`).WithArgs("test").WillReturnError(assert.AnError)
273+
assert.Error(t, rw.DeleteMetric("test"))
274+
})
275+
276+
t.Run("UpdateMetricExecError", func(t *testing.T) {
277+
conn.ExpectExec(`INSERT.+metric`).WithArgs(AnyArgs(8)...).WillReturnError(assert.AnError)
278+
assert.Error(t, rw.UpdateMetric("test", metrics.Metric{}))
269279
})
270280

271-
// check all expectations were met
272-
a.NoError(conn.ExpectationsWereMet())
281+
t.Run("DeletePresetError", func(t *testing.T) {
282+
conn.ExpectExec(`DELETE.+preset`).WithArgs("test").WillReturnError(assert.AnError)
283+
assert.Error(t, rw.DeletePreset("test"))
284+
})
285+
286+
t.Run("UpdatePresetExecError", func(t *testing.T) {
287+
conn.ExpectExec(`INSERT.+preset`).WithArgs(AnyArgs(3)...).WillReturnError(assert.AnError)
288+
assert.Error(t, rw.UpdatePreset("test", metrics.Preset{}))
289+
})
290+
291+
assert.NoError(t, conn.ExpectationsWereMet())
273292
}
274293

275-
// Additional tests for GetMetrics, WriteMetrics, DeleteMetric, UpdateMetric, DeletePreset, and UpdatePreset follow a similar pattern.
294+
func TestCreateMetric(t *testing.T) {
295+
conn, rw := newTestReaderWriter(t)
296+
297+
t.Run("Success", func(t *testing.T) {
298+
conn.ExpectExec(`INSERT.+metric`).WithArgs(AnyArgs(8)...).WillReturnResult(pgxmock.NewResult("INSERT", 1))
299+
assert.NoError(t, rw.CreateMetric("new_metric", metrics.Metric{}))
300+
})
301+
302+
t.Run("Duplicate", func(t *testing.T) {
303+
conn.ExpectExec(`INSERT.+metric`).WithArgs(AnyArgs(8)...).WillReturnError(&pgconn.PgError{Code: "23505"})
304+
assert.ErrorIs(t, rw.CreateMetric("existing_metric", metrics.Metric{}), metrics.ErrMetricExists)
305+
})
306+
307+
t.Run("ExecError", func(t *testing.T) {
308+
conn.ExpectExec(`INSERT.+metric`).WithArgs(AnyArgs(8)...).WillReturnError(assert.AnError)
309+
err := rw.CreateMetric("fail_metric", metrics.Metric{})
310+
assert.Error(t, err)
311+
assert.NotErrorIs(t, err, metrics.ErrMetricExists)
312+
})
313+
314+
assert.NoError(t, conn.ExpectationsWereMet())
315+
}
316+
317+
func TestCreatePreset(t *testing.T) {
318+
conn, rw := newTestReaderWriter(t)
319+
320+
t.Run("Success", func(t *testing.T) {
321+
conn.ExpectExec(`INSERT.+preset`).WithArgs(AnyArgs(3)...).WillReturnResult(pgxmock.NewResult("INSERT", 1))
322+
assert.NoError(t, rw.CreatePreset("new_preset", metrics.Preset{}))
323+
})
324+
325+
t.Run("Duplicate", func(t *testing.T) {
326+
conn.ExpectExec(`INSERT.+preset`).WithArgs(AnyArgs(3)...).WillReturnError(&pgconn.PgError{Code: "23505"})
327+
assert.ErrorIs(t, rw.CreatePreset("existing_preset", metrics.Preset{}), metrics.ErrPresetExists)
328+
})
329+
330+
t.Run("ExecError", func(t *testing.T) {
331+
conn.ExpectExec(`INSERT.+preset`).WithArgs(AnyArgs(3)...).WillReturnError(assert.AnError)
332+
err := rw.CreatePreset("fail_preset", metrics.Preset{})
333+
assert.Error(t, err)
334+
assert.NotErrorIs(t, err, metrics.ErrPresetExists)
335+
})
336+
337+
assert.NoError(t, conn.ExpectationsWereMet())
338+
}

0 commit comments

Comments
 (0)