Skip to content

Commit d27aacc

Browse files
authored
Merge pull request #24 from urbanogilson/test-cors
Add unit tests to CORS
2 parents dcdc8d9 + 90dcec9 commit d27aacc

File tree

4 files changed

+237
-19
lines changed

4 files changed

+237
-19
lines changed

src/cors.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#define ORIGIN_LIMIT 50
88
#define HEADER_LIMIT 50
99

10-
CorsConfig corsPolicy() {
10+
CorsConfig corsPolicy(void) {
1111
CorsConfig config = {
1212
.allowOrigin = malloc(ORIGIN_LIMIT * sizeof(char*)),
1313
.allowOriginCount = 0,
@@ -25,43 +25,55 @@ CorsConfig corsPolicy() {
2525
return config;
2626
}
2727

28-
void allowOrigin(CorsConfig *config, char *origin) {
28+
void freeCorsPolicy(CorsConfig config) {
29+
for (int i = 0; i < config.allowOriginCount; i++) {
30+
free(config.allowOrigin[i]);
31+
}
32+
free(config.allowOrigin);
33+
34+
for (int i = 0; i < config.headerCount; i++) {
35+
free(config.allowHeaders[i]);
36+
}
37+
free(config.allowHeaders);
38+
}
39+
40+
void allowOrigin(CorsConfig *const config, const char *const origin) {
2941
if (config->allowOriginCount >= ORIGIN_LIMIT) {
3042
return;
3143
}
3244

33-
config->allowOrigin[config->allowOriginCount++] = origin;
45+
config->allowOrigin[config->allowOriginCount++] = strdup(origin);
3446
}
3547

36-
void allowMethod(CorsConfig *config, HttpMethod method) {
48+
void allowMethod(CorsConfig *const config, HttpMethod method) {
3749
if (config->methodCount < 6) {
3850
config->allowMethods[config->methodCount++] = method;
3951
}
4052
}
4153

42-
void allowAnyOrigin(CorsConfig *config) {
54+
void allowAnyOrigin(CorsConfig *const config) {
4355
allowOrigin(config, "*");
4456
}
4557

46-
void allowAnyMethod(CorsConfig *config) {
47-
for (int i = 0; i < 6; i++) {
58+
void allowAnyMethod(CorsConfig *const config) {
59+
for (int i = HTTP_GET; i <= HTTP_OPTIONS; i++) {
4860
allowMethod(config, i);
4961
}
5062
}
5163

52-
void allowHeader(CorsConfig *config, char *header) {
64+
void allowHeader(CorsConfig *const config, const char *const header) {
5365
if (config->headerCount >= HEADER_LIMIT) {
5466
return;
5567
}
5668

57-
config->allowHeaders[config->headerCount++] = header;
69+
config->allowHeaders[config->headerCount++] = strdup(header);
5870
}
5971

60-
void allowAnyHeader(CorsConfig *config) {
72+
void allowAnyHeader(CorsConfig *const config) {
6173
allowHeader(config, "*");
6274
}
6375

64-
CorsConfig corsAllowAll() {
76+
CorsConfig corsAllowAll(void) {
6577
CorsConfig config = corsPolicy();
6678
allowAnyOrigin(&config);
6779
allowAnyMethod(&config);

src/include/cors.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ typedef struct {
1414
int headerCount;
1515
} CorsConfig;
1616

17-
CorsConfig corsPolicy();
17+
CorsConfig corsPolicy(void);
18+
void freeCorsPolicy(CorsConfig config);
1819

19-
void allowOrigin(CorsConfig *config, char *origin);
20-
void allowMethod(CorsConfig *config, HttpMethod method);
20+
void allowOrigin(CorsConfig *const config, const char *const origin);
21+
void allowMethod(CorsConfig *const config, HttpMethod method);
2122

22-
void allowAnyOrigin(CorsConfig *config);
23-
void allowAnyMethod(CorsConfig *config);
23+
void allowAnyOrigin(CorsConfig *const config);
24+
void allowAnyMethod(CorsConfig *const config);
2425

25-
void allowHeader(CorsConfig *config, char *header);
26-
void allowAnyHeader(CorsConfig *config);
26+
void allowHeader(CorsConfig *const config, const char *const header);
27+
void allowAnyHeader(CorsConfig *const config);
2728

28-
CorsConfig corsAllowAll();
29+
CorsConfig corsAllowAll(void);
2930

3031
#endif

test/cors_test.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "../src/include/lavandula_test.h"
5+
#include "../src/include/cors.h"
6+
7+
void testCorsPolicyInit() {
8+
CorsConfig config = corsPolicy();
9+
10+
expectNotNull(config.allowOrigin);
11+
expect(config.allowOriginCount, toBe(0));
12+
expect(config.allowMethods[0], toBe(0));
13+
expect(config.methodCount, toBe(0));
14+
expectNotNull(config.allowHeaders);
15+
expect(config.headerCount, toBe(0));
16+
17+
freeCorsPolicy(config);
18+
}
19+
20+
void testAllowOrigin() {
21+
CorsConfig config = corsPolicy();
22+
allowOrigin(&config, "https://example.com");
23+
expect(config.allowOriginCount, toBe(1));
24+
expect(strcmp(config.allowOrigin[0], "https://example.com"), toBe(0));
25+
26+
allowOrigin(&config, "https://test.com");
27+
expect(config.allowOriginCount, toBe(2));
28+
expect(strcmp(config.allowOrigin[1], "https://test.com"), toBe(0));
29+
30+
freeCorsPolicy(config);
31+
}
32+
33+
void testAllowOriginLimit() {
34+
CorsConfig config = corsPolicy();
35+
36+
// Add 50 origins (the limit)
37+
for (int i = 0; i < 50; i++) {
38+
allowOrigin(&config, "https://example.com");
39+
}
40+
expect(config.allowOriginCount, toBe(50));
41+
42+
// Try to add one more
43+
allowOrigin(&config, "https://overflow.com");
44+
expect(config.allowOriginCount, toBe(50));
45+
46+
freeCorsPolicy(config);
47+
}
48+
49+
void testAllowMethod() {
50+
CorsConfig config = corsPolicy();
51+
52+
allowMethod(&config, HTTP_GET);
53+
expect(config.methodCount, toBe(1));
54+
expect(config.allowMethods[0], toBe(HTTP_GET));
55+
56+
allowMethod(&config, HTTP_POST);
57+
expect(config.methodCount, toBe(2));
58+
expect(config.allowMethods[1], toBe(HTTP_POST));
59+
60+
freeCorsPolicy(config);
61+
}
62+
63+
void testAllowMethodLimit() {
64+
CorsConfig config = corsPolicy();
65+
66+
// Add all 6 methods (GET, POST, PUT, DELETE, PATCH, OPTIONS)
67+
for (int i = 0; i < 6; i++) {
68+
allowMethod(&config, i);
69+
}
70+
expect(config.methodCount, toBe(6));
71+
72+
// Try to add one more
73+
allowMethod(&config, (HttpMethod)0xffff);
74+
expect(config.methodCount, toBe(6));
75+
76+
freeCorsPolicy(config);
77+
}
78+
79+
void testAllowAnyOrigin() {
80+
CorsConfig config = corsPolicy();
81+
82+
allowAnyOrigin(&config);
83+
expect(config.allowOriginCount, toBe(1));
84+
expect(strcmp(config.allowOrigin[0], "*"), toBe(0));
85+
86+
freeCorsPolicy(config);
87+
}
88+
89+
void testAllowAnyMethod() {
90+
CorsConfig config = corsPolicy();
91+
92+
allowAnyMethod(&config);
93+
expect(config.methodCount, toBe(6));
94+
95+
for (int i = 0; i < 6; i++) {
96+
expect(config.allowMethods[i], toBe((HttpMethod)i));
97+
}
98+
99+
freeCorsPolicy(config);
100+
}
101+
102+
void testAllowHeader() {
103+
CorsConfig config = corsPolicy();
104+
105+
allowHeader(&config, "Content-Type");
106+
expect(config.headerCount, toBe(1));
107+
expect(strcmp(config.allowHeaders[0], "Content-Type"), toBe(0));
108+
109+
allowHeader(&config, "Authorization");
110+
expect(config.headerCount, toBe(2));
111+
expect(strcmp(config.allowHeaders[1], "Authorization"), toBe(0));
112+
113+
freeCorsPolicy(config);
114+
}
115+
116+
void testAllowHeaderLimit() {
117+
CorsConfig config = corsPolicy();
118+
119+
// Add 50 headers (the limit)
120+
for (int i = 0; i < 50; i++) {
121+
allowHeader(&config, "X-Custom-Header");
122+
}
123+
expect(config.headerCount, toBe(50));
124+
125+
// Try to add one more
126+
allowHeader(&config, "X-Overflow");
127+
expect(config.headerCount, toBe(50));
128+
129+
freeCorsPolicy(config);
130+
}
131+
132+
void testAllowAnyHeader() {
133+
CorsConfig config = corsPolicy();
134+
135+
allowAnyHeader(&config);
136+
expect(config.headerCount, toBe(1));
137+
expect(strcmp(config.allowHeaders[0], "*"), toBe(0));
138+
139+
freeCorsPolicy(config);
140+
}
141+
142+
void testCorsAllowAll() {
143+
CorsConfig config = corsAllowAll();
144+
145+
// Check that origin is set to "*"
146+
expect(config.allowOriginCount, toBe(1));
147+
expect(strcmp(config.allowOrigin[0], "*"), toBe(0));
148+
149+
// Check that all methods are allowed
150+
expect(config.methodCount, toBe(6));
151+
for (int i = 0; i < 6; i++) {
152+
expect(config.allowMethods[i], toBe((HttpMethod)i));
153+
}
154+
freeCorsPolicy(config);
155+
}
156+
157+
void testAllowOriginWithDynamicStrings() {
158+
CorsConfig config = corsPolicy();
159+
160+
char *dynamic_origin = strdup("https://dynamic.com");
161+
allowOrigin(&config, dynamic_origin);
162+
free(dynamic_origin);
163+
expect(config.allowOriginCount, toBe(1));
164+
expect(strcmp(config.allowOrigin[0], "https://dynamic.com"), toBe(0));
165+
166+
allowOrigin(&config, "https://literal.com");
167+
expect(config.allowOriginCount, toBe(2));
168+
expect(strcmp(config.allowOrigin[1], "https://literal.com"), toBe(0));
169+
170+
freeCorsPolicy(config);
171+
}
172+
173+
void testAllowHeaderWithDynamicStrings() {
174+
CorsConfig config = corsPolicy();
175+
176+
char *dynamic_header = strdup("X-Custom-Header");
177+
allowHeader(&config, dynamic_header);
178+
free(dynamic_header);
179+
expect(config.headerCount, toBe(1));
180+
expect(strcmp(config.allowHeaders[0], "X-Custom-Header"), toBe(0));
181+
182+
allowHeader(&config, "Authorization");
183+
expect(config.headerCount, toBe(2));
184+
expect(strcmp(config.allowHeaders[1], "Authorization"), toBe(0));
185+
186+
freeCorsPolicy(config);
187+
}
188+
189+
void runCorsTests() {
190+
runTest(testCorsPolicyInit);
191+
runTest(testAllowOrigin);
192+
runTest(testAllowOriginLimit);
193+
runTest(testAllowMethod);
194+
runTest(testAllowMethodLimit);
195+
runTest(testAllowAnyOrigin);
196+
runTest(testAllowAnyMethod);
197+
runTest(testAllowHeader);
198+
runTest(testAllowHeaderLimit);
199+
runTest(testAllowAnyHeader);
200+
runTest(testCorsAllowAll);
201+
runTest(testAllowOriginWithDynamicStrings);
202+
runTest(testAllowHeaderWithDynamicStrings);
203+
}

test/tests.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ void runUtilsTests();
99
void runAuthTests();
1010
void runJsonTests();
1111
void runBase64Tests();
12+
void runCorsTests();
1213

1314
int main() {
1415
testsRan = 0;
@@ -23,6 +24,7 @@ int main() {
2324
runAuthTests();
2425
runJsonTests();
2526
runBase64Tests();
27+
runCorsTests();
2628

2729
printf("=== Lavandula Test Results ===\n");
2830
testResults();

0 commit comments

Comments
 (0)