Skip to content

Commit ad61dac

Browse files
dciangotclaude
andcommitted
test: add unit tests for core utility functions
Add comprehensive unit tests covering: - stringToHex: hex encoding with trailing zero removal - parsingTimeFromString: timestamp parsing validation - prepareImage: image path and prefix handling - GetSessionContext: HTTP header extraction - GetSessionContextMessage: session message formatting - checkIfJidExists: JID lookup verification - removeJID: JID removal functionality All tests pass successfully. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 1cc7299 commit ad61dac

File tree

2 files changed

+305
-0
lines changed

2 files changed

+305
-0
lines changed

pkg/slurm/func_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package slurm
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"testing"
7+
)
8+
9+
func TestGetSessionContext(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
headerValue string
13+
expectedResult string
14+
}{
15+
{
16+
name: "header present",
17+
headerValue: "session-123",
18+
expectedResult: "session-123",
19+
},
20+
{
21+
name: "header empty",
22+
headerValue: "",
23+
expectedResult: "NoSessionFound#0",
24+
},
25+
{
26+
name: "header with special characters",
27+
headerValue: "session@456#abc",
28+
expectedResult: "session@456#abc",
29+
},
30+
}
31+
32+
for _, tt := range tests {
33+
t.Run(tt.name, func(t *testing.T) {
34+
req := httptest.NewRequest(http.MethodGet, "/test", nil)
35+
if tt.headerValue != "" {
36+
req.Header.Set("InterLink-Http-Session", tt.headerValue)
37+
}
38+
39+
result := GetSessionContext(req)
40+
if result != tt.expectedResult {
41+
t.Errorf("GetSessionContext() = %q, want %q", result, tt.expectedResult)
42+
}
43+
})
44+
}
45+
}
46+
47+
func TestGetSessionContextMessage(t *testing.T) {
48+
tests := []struct {
49+
name string
50+
sessionContext string
51+
expectedResult string
52+
}{
53+
{
54+
name: "normal session",
55+
sessionContext: "session-123",
56+
expectedResult: "HTTP InterLink session session-123: ",
57+
},
58+
{
59+
name: "empty session",
60+
sessionContext: "",
61+
expectedResult: "HTTP InterLink session : ",
62+
},
63+
{
64+
name: "default no session",
65+
sessionContext: "NoSessionFound#0",
66+
expectedResult: "HTTP InterLink session NoSessionFound#0: ",
67+
},
68+
}
69+
70+
for _, tt := range tests {
71+
t.Run(tt.name, func(t *testing.T) {
72+
result := GetSessionContextMessage(tt.sessionContext)
73+
if result != tt.expectedResult {
74+
t.Errorf("GetSessionContextMessage(%q) = %q, want %q", tt.sessionContext, result, tt.expectedResult)
75+
}
76+
})
77+
}
78+
}

pkg/slurm/prepare_test.go

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package slurm
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
)
10+
11+
func TestStringToHex(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
input string
15+
expected string
16+
}{
17+
{
18+
name: "simple string",
19+
input: "test",
20+
expected: "74657374",
21+
},
22+
{
23+
name: "empty string",
24+
input: "",
25+
expected: "",
26+
},
27+
{
28+
name: "string with spaces",
29+
input: "a b",
30+
expected: "6162",
31+
},
32+
{
33+
name: "special characters",
34+
input: "a-b_c",
35+
expected: "612d625f63",
36+
},
37+
}
38+
39+
for _, tt := range tests {
40+
t.Run(tt.name, func(t *testing.T) {
41+
result := stringToHex(tt.input)
42+
if result != tt.expected {
43+
t.Errorf("stringToHex(%q) = %q, want %q", tt.input, result, tt.expected)
44+
}
45+
})
46+
}
47+
}
48+
49+
func TestParsingTimeFromString(t *testing.T) {
50+
ctx := context.Background()
51+
timestampFormat := "2006-01-02 15:04:05.999999999 -0700 MST"
52+
53+
tests := []struct {
54+
name string
55+
input string
56+
shouldError bool
57+
}{
58+
{
59+
name: "valid timestamp",
60+
input: "2024-01-15 10:30:45.123456789 +0000 UTC",
61+
shouldError: false,
62+
},
63+
{
64+
name: "invalid format - missing fields",
65+
input: "2024-01-15 10:30:45",
66+
shouldError: true,
67+
},
68+
{
69+
name: "invalid format - wrong separator",
70+
input: "2024-01-15T10:30:45.123456789+0000UTC",
71+
shouldError: true,
72+
},
73+
{
74+
name: "empty string",
75+
input: "",
76+
shouldError: true,
77+
},
78+
}
79+
80+
for _, tt := range tests {
81+
t.Run(tt.name, func(t *testing.T) {
82+
result, err := parsingTimeFromString(ctx, tt.input, timestampFormat)
83+
if tt.shouldError {
84+
if err == nil {
85+
t.Errorf("parsingTimeFromString(%q) expected error but got nil", tt.input)
86+
}
87+
} else {
88+
if err != nil {
89+
t.Errorf("parsingTimeFromString(%q) unexpected error: %v", tt.input, err)
90+
}
91+
if result.IsZero() {
92+
t.Errorf("parsingTimeFromString(%q) returned zero time", tt.input)
93+
}
94+
}
95+
})
96+
}
97+
}
98+
99+
func TestPrepareImage(t *testing.T) {
100+
ctx := context.Background()
101+
102+
tests := []struct {
103+
name string
104+
config SlurmConfig
105+
metadata metav1.ObjectMeta
106+
containerImage string
107+
expectedContains string
108+
}{
109+
{
110+
name: "image with default prefix",
111+
config: SlurmConfig{
112+
ImagePrefix: "docker://",
113+
},
114+
metadata: metav1.ObjectMeta{},
115+
containerImage: "ubuntu:latest",
116+
expectedContains: "docker://ubuntu:latest",
117+
},
118+
{
119+
name: "image with custom prefix from annotation",
120+
config: SlurmConfig{
121+
ImagePrefix: "docker://",
122+
},
123+
metadata: metav1.ObjectMeta{
124+
Annotations: map[string]string{
125+
"slurm-job.vk.io/image-root": "oras://",
126+
},
127+
},
128+
containerImage: "myimage:v1",
129+
expectedContains: "oras://myimage:v1",
130+
},
131+
{
132+
name: "absolute path image",
133+
config: SlurmConfig{
134+
ImagePrefix: "docker://",
135+
},
136+
metadata: metav1.ObjectMeta{},
137+
containerImage: "/path/to/image.sif",
138+
expectedContains: "/path/to/image.sif",
139+
},
140+
{
141+
name: "image already has prefix",
142+
config: SlurmConfig{
143+
ImagePrefix: "docker://",
144+
},
145+
metadata: metav1.ObjectMeta{},
146+
containerImage: "docker://nginx:alpine",
147+
expectedContains: "docker://nginx:alpine",
148+
},
149+
}
150+
151+
for _, tt := range tests {
152+
t.Run(tt.name, func(t *testing.T) {
153+
result := prepareImage(ctx, tt.config, tt.metadata, tt.containerImage)
154+
if result != tt.expectedContains {
155+
t.Errorf("prepareImage() = %q, want %q", result, tt.expectedContains)
156+
}
157+
})
158+
}
159+
}
160+
161+
func TestCheckIfJidExists(t *testing.T) {
162+
ctx := context.Background()
163+
jids := make(map[string]*JidStruct)
164+
165+
// Add some test data
166+
jids["uid-1"] = &JidStruct{
167+
PodUID: "uid-1",
168+
PodNamespace: "default",
169+
JID: "12345",
170+
StartTime: time.Now(),
171+
}
172+
173+
tests := []struct {
174+
name string
175+
uid string
176+
expected bool
177+
}{
178+
{
179+
name: "existing JID",
180+
uid: "uid-1",
181+
expected: true,
182+
},
183+
{
184+
name: "non-existing JID",
185+
uid: "uid-2",
186+
expected: false,
187+
},
188+
{
189+
name: "empty uid",
190+
uid: "",
191+
expected: false,
192+
},
193+
}
194+
195+
for _, tt := range tests {
196+
t.Run(tt.name, func(t *testing.T) {
197+
result := checkIfJidExists(ctx, &jids, tt.uid)
198+
if result != tt.expected {
199+
t.Errorf("checkIfJidExists(%q) = %v, want %v", tt.uid, result, tt.expected)
200+
}
201+
})
202+
}
203+
}
204+
205+
func TestRemoveJID(t *testing.T) {
206+
jids := make(map[string]*JidStruct)
207+
jids["uid-1"] = &JidStruct{
208+
PodUID: "uid-1",
209+
PodNamespace: "default",
210+
JID: "12345",
211+
}
212+
jids["uid-2"] = &JidStruct{
213+
PodUID: "uid-2",
214+
PodNamespace: "default",
215+
JID: "67890",
216+
}
217+
218+
removeJID("uid-1", &jids)
219+
220+
if _, exists := jids["uid-1"]; exists {
221+
t.Error("removeJID() failed to remove uid-1")
222+
}
223+
224+
if _, exists := jids["uid-2"]; !exists {
225+
t.Error("removeJID() incorrectly removed uid-2")
226+
}
227+
}

0 commit comments

Comments
 (0)