test(ops): add partition status unit tests and fix test mocks
- Add ops_partition_test.go with comprehensive unit tests: - Test partitioned table scenario - Test needs_partitioning warning level - Test info level warning (50K-100K rows) - Test below threshold scenario - Test error handling - Test nil repo handling - Fix ops_repo_mock_test.go to implement new interface methods: - IsUsageLogsPartitioned - GetUsageLogsRowCount - GetUsageLogsPartitionCount - Fix admin_basic_handlers_test.go password length: - Change "pass123" to "password123" (min=8 enforced)
This commit is contained in:
@@ -75,7 +75,7 @@ func TestUserHandlerEndpoints(t *testing.T) {
|
||||
router.ServeHTTP(rec, req)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
|
||||
createBody := map[string]any{"email": "new@example.com", "password": "pass123", "balance": 1, "concurrency": 2}
|
||||
createBody := map[string]any{"email": "new@example.com", "password": "password123", "balance": 1, "concurrency": 2}
|
||||
body, _ := json.Marshal(createBody)
|
||||
rec = httptest.NewRecorder()
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/v1/admin/users", bytes.NewReader(body))
|
||||
|
||||
280
backend/internal/service/ops_partition_test.go
Normal file
280
backend/internal/service/ops_partition_test.go
Normal file
@@ -0,0 +1,280 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// mockOpsRepoForPartition is a mock for testing partition status
|
||||
type mockOpsRepoForPartition struct {
|
||||
isPartitioned bool
|
||||
isPartitionedErr error
|
||||
rowCount int64
|
||||
rowCountErr error
|
||||
partitionCount int
|
||||
partitionCountErr error
|
||||
}
|
||||
|
||||
func (m *mockOpsRepoForPartition) IsUsageLogsPartitioned(ctx context.Context) (bool, error) {
|
||||
return m.isPartitioned, m.isPartitionedErr
|
||||
}
|
||||
|
||||
func (m *mockOpsRepoForPartition) GetUsageLogsRowCount(ctx context.Context) (int64, error) {
|
||||
return m.rowCount, m.rowCountErr
|
||||
}
|
||||
|
||||
func (m *mockOpsRepoForPartition) GetUsageLogsPartitionCount(ctx context.Context) (int, error) {
|
||||
return m.partitionCount, m.partitionCountErr
|
||||
}
|
||||
|
||||
// Implement minimal OpsRepository interface for testing
|
||||
func (m *mockOpsRepoForPartition) InsertErrorLog(ctx context.Context, input *OpsInsertErrorLogInput) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) BatchInsertErrorLogs(ctx context.Context, inputs []*OpsInsertErrorLogInput) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) ListErrorLogs(ctx context.Context, filter *OpsErrorLogFilter) (*OpsErrorLogList, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetErrorLogByID(ctx context.Context, id int64) (*OpsErrorLogDetail, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) ListRequestDetails(ctx context.Context, filter *OpsRequestDetailFilter) ([]*OpsRequestDetail, int64, error) {
|
||||
return nil, 0, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) BatchInsertSystemLogs(ctx context.Context, inputs []*OpsInsertSystemLogInput) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) ListSystemLogs(ctx context.Context, filter *OpsSystemLogFilter) (*OpsSystemLogList, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) DeleteSystemLogs(ctx context.Context, filter *OpsSystemLogCleanupFilter) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) InsertSystemLogCleanupAudit(ctx context.Context, input *OpsSystemLogCleanupAudit) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) InsertRetryAttempt(ctx context.Context, input *OpsInsertRetryAttemptInput) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpdateRetryAttempt(ctx context.Context, input *OpsUpdateRetryAttemptInput) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetLatestRetryAttemptForError(ctx context.Context, sourceErrorID int64) (*OpsRetryAttempt, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) ListRetryAttemptsByErrorID(ctx context.Context, sourceErrorID int64, limit int) ([]*OpsRetryAttempt, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpdateErrorResolution(ctx context.Context, errorID int64, resolved bool, resolvedByUserID *int64, resolvedRetryID *int64, resolvedAt *time.Time) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetWindowStats(ctx context.Context, filter *OpsDashboardFilter) (*OpsWindowStats, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetRealtimeTrafficSummary(ctx context.Context, filter *OpsDashboardFilter) (*OpsRealtimeTrafficSummary, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetDashboardOverview(ctx context.Context, filter *OpsDashboardFilter) (*OpsDashboardOverview, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetThroughputTrend(ctx context.Context, filter *OpsDashboardFilter, bucketSeconds int) (*OpsThroughputTrendResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetLatencyHistogram(ctx context.Context, filter *OpsDashboardFilter) (*OpsLatencyHistogramResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetErrorTrend(ctx context.Context, filter *OpsDashboardFilter, bucketSeconds int) (*OpsErrorTrendResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetErrorDistribution(ctx context.Context, filter *OpsDashboardFilter) (*OpsErrorDistributionResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetOpenAITokenStats(ctx context.Context, filter *OpsOpenAITokenStatsFilter) (*OpsOpenAITokenStatsResponse, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) InsertSystemMetrics(ctx context.Context, input *OpsInsertSystemMetricsInput) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetLatestSystemMetrics(ctx context.Context, windowMinutes int) (*OpsSystemMetricsSnapshot, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpsertJobHeartbeat(ctx context.Context, input *OpsUpsertJobHeartbeatInput) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) ListJobHeartbeats(ctx context.Context) ([]*OpsJobHeartbeat, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) ListAlertRules(ctx context.Context) ([]*OpsAlertRule, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) CreateAlertRule(ctx context.Context, input *OpsAlertRule) (*OpsAlertRule, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpdateAlertRule(ctx context.Context, input *OpsAlertRule) (*OpsAlertRule, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) DeleteAlertRule(ctx context.Context, id int64) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) ListAlertEvents(ctx context.Context, filter *OpsAlertEventFilter) ([]*OpsAlertEvent, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetAlertEventByID(ctx context.Context, eventID int64) (*OpsAlertEvent, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetActiveAlertEvent(ctx context.Context, ruleID int64) (*OpsAlertEvent, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetLatestAlertEvent(ctx context.Context, ruleID int64) (*OpsAlertEvent, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) CreateAlertEvent(ctx context.Context, event *OpsAlertEvent) (*OpsAlertEvent, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpdateAlertEventStatus(ctx context.Context, eventID int64, status string, resolvedAt *time.Time) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpdateAlertEventEmailSent(ctx context.Context, eventID int64, emailSent bool) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) CreateAlertSilence(ctx context.Context, input *OpsAlertSilence) (*OpsAlertSilence, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) IsAlertSilenced(ctx context.Context, ruleID int64, platform string, groupID *int64, region *string, now time.Time) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpsertHourlyMetrics(ctx context.Context, startTime, endTime time.Time) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) UpsertDailyMetrics(ctx context.Context, startTime, endTime time.Time) error {
|
||||
return nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetLatestHourlyBucketStart(ctx context.Context) (time.Time, bool, error) {
|
||||
return time.Time{}, false, nil
|
||||
}
|
||||
func (m *mockOpsRepoForPartition) GetLatestDailyBucketDate(ctx context.Context) (time.Time, bool, error) {
|
||||
return time.Time{}, false, nil
|
||||
}
|
||||
|
||||
func TestGetUsageLogsPartitionStatus_Partitioned(t *testing.T) {
|
||||
mock := &mockOpsRepoForPartition{
|
||||
isPartitioned: true,
|
||||
rowCount: 500000,
|
||||
partitionCount: 12,
|
||||
}
|
||||
|
||||
svc := &OpsService{opsRepo: mock}
|
||||
|
||||
status, err := svc.GetUsageLogsPartitionStatus(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !status.IsPartitioned {
|
||||
t.Error("expected IsPartitioned to be true")
|
||||
}
|
||||
if status.RowCount != 500000 {
|
||||
t.Errorf("expected RowCount 500000, got %d", status.RowCount)
|
||||
}
|
||||
if status.PartitionCount != 12 {
|
||||
t.Errorf("expected PartitionCount 12, got %d", status.PartitionCount)
|
||||
}
|
||||
if status.WarningLevel != "none" {
|
||||
t.Errorf("expected WarningLevel 'none', got %s", status.WarningLevel)
|
||||
}
|
||||
if status.NeedsPartitioning {
|
||||
t.Error("expected NeedsPartitioning to be false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUsageLogsPartitionStatus_NotPartitioned_NeedsPartitioning(t *testing.T) {
|
||||
mock := &mockOpsRepoForPartition{
|
||||
isPartitioned: false,
|
||||
rowCount: 150000, // Above threshold of 100000
|
||||
}
|
||||
|
||||
svc := &OpsService{opsRepo: mock}
|
||||
|
||||
status, err := svc.GetUsageLogsPartitionStatus(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if status.IsPartitioned {
|
||||
t.Error("expected IsPartitioned to be false")
|
||||
}
|
||||
if !status.NeedsPartitioning {
|
||||
t.Error("expected NeedsPartitioning to be true")
|
||||
}
|
||||
if status.WarningLevel != "warning" {
|
||||
t.Errorf("expected WarningLevel 'warning', got %s", status.WarningLevel)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUsageLogsPartitionStatus_NotPartitioned_BelowThreshold(t *testing.T) {
|
||||
mock := &mockOpsRepoForPartition{
|
||||
isPartitioned: false,
|
||||
rowCount: 30000, // Well below threshold (50000)
|
||||
}
|
||||
|
||||
svc := &OpsService{opsRepo: mock}
|
||||
|
||||
status, err := svc.GetUsageLogsPartitionStatus(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if status.NeedsPartitioning {
|
||||
t.Error("expected NeedsPartitioning to be false")
|
||||
}
|
||||
if status.WarningLevel != "none" {
|
||||
t.Errorf("expected WarningLevel 'none', got %s", status.WarningLevel)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUsageLogsPartitionStatus_NotPartitioned_InfoLevel(t *testing.T) {
|
||||
mock := &mockOpsRepoForPartition{
|
||||
isPartitioned: false,
|
||||
rowCount: 75000, // Between 50000 and 100000
|
||||
}
|
||||
|
||||
svc := &OpsService{opsRepo: mock}
|
||||
|
||||
status, err := svc.GetUsageLogsPartitionStatus(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if status.NeedsPartitioning {
|
||||
t.Error("expected NeedsPartitioning to be false")
|
||||
}
|
||||
if status.WarningLevel != "info" {
|
||||
t.Errorf("expected WarningLevel 'info', got %s", status.WarningLevel)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUsageLogsPartitionStatus_Error(t *testing.T) {
|
||||
mock := &mockOpsRepoForPartition{
|
||||
isPartitionedErr: errors.New("db error"),
|
||||
}
|
||||
|
||||
svc := &OpsService{opsRepo: mock}
|
||||
|
||||
_, err := svc.GetUsageLogsPartitionStatus(context.Background())
|
||||
if err == nil {
|
||||
t.Error("expected error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUsageLogsPartitionStatus_NilRepo(t *testing.T) {
|
||||
svc := &OpsService{opsRepo: nil}
|
||||
|
||||
_, err := svc.GetUsageLogsPartitionStatus(context.Background())
|
||||
if err == nil {
|
||||
t.Error("expected error for nil repo, got nil")
|
||||
}
|
||||
}
|
||||
@@ -205,4 +205,16 @@ func (m *opsRepoMock) GetLatestDailyBucketDate(ctx context.Context) (time.Time,
|
||||
return time.Time{}, false, nil
|
||||
}
|
||||
|
||||
func (m *opsRepoMock) IsUsageLogsPartitioned(ctx context.Context) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (m *opsRepoMock) GetUsageLogsRowCount(ctx context.Context) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *opsRepoMock) GetUsageLogsPartitionCount(ctx context.Context) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var _ OpsRepository = (*opsRepoMock)(nil)
|
||||
|
||||
Reference in New Issue
Block a user