1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
package api
import (
"context"
"errors"
"testing"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"albatross-2026-backend/config"
"albatross-2026-backend/db"
)
// mockQuerier implements db.Querier for testing.
type mockQuerier struct {
db.Querier
getGameByIDFunc func(ctx context.Context, gameID int32) (db.GetGameByIDRow, error)
}
func (m *mockQuerier) GetGameByID(ctx context.Context, gameID int32) (db.GetGameByIDRow, error) {
if m.getGameByIDFunc != nil {
return m.getGameByIDFunc(ctx, gameID)
}
return db.GetGameByIDRow{}, pgx.ErrNoRows
}
// mockTxManager implements db.TxManager for testing.
type mockTxManager struct{}
func (m *mockTxManager) RunInTx(ctx context.Context, fn func(q db.Querier) error) error {
return fn(&mockQuerier{})
}
// mockGameHub implements GameHubInterface for testing.
type mockGameHub struct {
calcCodeSizeResult int
enqueueErr error
}
func (m *mockGameHub) CalcCodeSize(_ string, _ string) int {
return m.calcCodeSizeResult
}
func (m *mockGameHub) EnqueueTestTasks(_ context.Context, _, _, _ int, _, _ string) error {
return m.enqueueErr
}
// mockAuthenticator implements AuthenticatorInterface for testing.
type mockAuthenticator struct {
loginResult int
loginErr error
}
func (m *mockAuthenticator) Login(_ context.Context, _, _ string) (int, error) {
return m.loginResult, m.loginErr
}
func TestPostGamePlaySubmit_GameNotFound(t *testing.T) {
h := Handler{
q: &mockQuerier{},
txm: &mockTxManager{},
hub: &mockGameHub{},
auth: &mockAuthenticator{},
conf: &config.Config{},
}
user := &db.User{UserID: 1}
resp, err := h.PostGamePlaySubmit(context.Background(), PostGamePlaySubmitRequestObject{
GameID: 999,
Body: &PostGamePlaySubmitJSONRequestBody{Code: "test"},
}, user)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, ok := resp.(PostGamePlaySubmit404JSONResponse); !ok {
t.Errorf("expected 404 response, got %T", resp)
}
}
func TestPostGamePlaySubmit_GameNotRunning(t *testing.T) {
h := Handler{
q: &mockQuerier{
getGameByIDFunc: func(_ context.Context, _ int32) (db.GetGameByIDRow, error) {
return db.GetGameByIDRow{
GameID: 1,
Language: "php",
StartedAt: pgtype.Timestamp{
Valid: false,
},
}, nil
},
},
txm: &mockTxManager{},
hub: &mockGameHub{calcCodeSizeResult: 10},
auth: &mockAuthenticator{},
conf: &config.Config{},
}
user := &db.User{UserID: 1}
resp, err := h.PostGamePlaySubmit(context.Background(), PostGamePlaySubmitRequestObject{
GameID: 1,
Body: &PostGamePlaySubmitJSONRequestBody{Code: "<?php echo 1;"},
}, user)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if r, ok := resp.(PostGamePlaySubmit403JSONResponse); !ok {
t.Errorf("expected 403 response, got %T", resp)
} else if r.Message != "Game is not running" {
t.Errorf("unexpected message: %s", r.Message)
}
}
func TestPostLogin_AuthFailure(t *testing.T) {
h := Handler{
q: &mockQuerier{},
txm: &mockTxManager{},
hub: &mockGameHub{},
auth: &mockAuthenticator{loginErr: errors.New("invalid credentials")},
conf: &config.Config{},
}
resp, err := h.PostLogin(context.Background(), PostLoginRequestObject{
Body: &PostLoginJSONRequestBody{Username: "user", Password: "wrong"},
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, ok := resp.(PostLogin401JSONResponse); !ok {
t.Errorf("expected 401 response, got %T", resp)
}
}
|