Skip to content

Commit aeaba92

Browse files
authored
more c tests
1 parent 498ef09 commit aeaba92

File tree

9 files changed

+967
-25
lines changed

9 files changed

+967
-25
lines changed

sdk/cosmos/azure_data_cosmos_native/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ corrosion_import_crate(
2424

2525
set(TEST_FILES
2626
./c_tests/version.c
27-
./c_tests/item_crud.c)
27+
./c_tests/item_crud.c
28+
./c_tests/context_memory_management.c
29+
./c_tests/error_handling.c)
2830

2931
foreach(test_file ${TEST_FILES})
3032
get_filename_component(test_name ${test_file} NAME_WE)
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <time.h>
8+
#include "../include/azurecosmos.h"
9+
10+
#define TEST_PASS 0
11+
#define TEST_FAIL 1
12+
13+
// Test counter
14+
static int tests_run = 0;
15+
static int tests_passed = 0;
16+
17+
void report_test(const char *test_name, int passed) {
18+
tests_run++;
19+
if (passed) {
20+
tests_passed++;
21+
printf("✓ PASS: %s\n", test_name);
22+
} else {
23+
printf("✗ FAIL: %s\n", test_name);
24+
}
25+
}
26+
27+
// Test 1: Runtime context lifecycle
28+
int test_runtime_context_lifecycle() {
29+
printf("\n--- Test: runtime_context_lifecycle ---\n");
30+
31+
cosmos_runtime_context *runtime = cosmos_runtime_context_create(NULL);
32+
if (!runtime) {
33+
printf("Failed to create runtime context\n");
34+
return TEST_FAIL;
35+
}
36+
printf("Created runtime context successfully\n");
37+
38+
// Free it
39+
cosmos_runtime_context_free(runtime);
40+
printf("Freed runtime context successfully\n");
41+
42+
return TEST_PASS;
43+
}
44+
45+
// Test 2: Stack-allocated call context
46+
int test_call_context_stack_allocated() {
47+
printf("\n--- Test: call_context_stack_allocated ---\n");
48+
49+
cosmos_runtime_context *runtime = cosmos_runtime_context_create(NULL);
50+
if (!runtime) {
51+
printf("Failed to create runtime context\n");
52+
return TEST_FAIL;
53+
}
54+
55+
// Stack-allocated context
56+
cosmos_call_context ctx;
57+
ctx.runtime_context = runtime;
58+
ctx.include_error_details = false;
59+
60+
printf("Created stack-allocated call context\n");
61+
62+
// Use it for a simple operation (get version)
63+
const char *version = cosmos_version();
64+
if (!version) {
65+
printf("Failed to get version\n");
66+
cosmos_runtime_context_free(runtime);
67+
return TEST_FAIL;
68+
}
69+
printf("Successfully used stack-allocated context (version: %s)\n", version);
70+
71+
cosmos_runtime_context_free(runtime);
72+
return TEST_PASS;
73+
}
74+
75+
// Test 3: Heap-allocated call context
76+
int test_call_context_heap_allocated() {
77+
printf("\n--- Test: call_context_heap_allocated ---\n");
78+
79+
cosmos_runtime_context *runtime = cosmos_runtime_context_create(NULL);
80+
if (!runtime) {
81+
printf("Failed to create runtime context\n");
82+
return TEST_FAIL;
83+
}
84+
85+
// Heap-allocated context
86+
cosmos_call_context *ctx = cosmos_call_context_create(runtime, false);
87+
if (!ctx) {
88+
printf("Failed to create heap-allocated call context\n");
89+
cosmos_runtime_context_free(runtime);
90+
return TEST_FAIL;
91+
}
92+
printf("Created heap-allocated call context\n");
93+
94+
// Use it for a simple operation (get version)
95+
const char *version = cosmos_version();
96+
if (!version) {
97+
printf("Failed to get version\n");
98+
cosmos_call_context_free(ctx);
99+
cosmos_runtime_context_free(runtime);
100+
return TEST_FAIL;
101+
}
102+
printf("Successfully used heap-allocated context (version: %s)\n", version);
103+
104+
cosmos_call_context_free(ctx);
105+
cosmos_runtime_context_free(runtime);
106+
return TEST_PASS;
107+
}
108+
109+
// Test 4: Call context reuse
110+
int test_call_context_reuse() {
111+
printf("\n--- Test: call_context_reuse ---\n");
112+
113+
const char *endpoint = getenv("AZURE_COSMOS_ENDPOINT");
114+
const char *key = getenv("AZURE_COSMOS_KEY");
115+
116+
if (!endpoint || !key) {
117+
printf("Skipping test - requires AZURE_COSMOS_ENDPOINT and AZURE_COSMOS_KEY\n");
118+
return TEST_PASS; // Not a failure, just skipped
119+
}
120+
121+
cosmos_runtime_context *runtime = cosmos_runtime_context_create(NULL);
122+
if (!runtime) {
123+
printf("Failed to create runtime context\n");
124+
return TEST_FAIL;
125+
}
126+
127+
cosmos_call_context ctx;
128+
ctx.runtime_context = runtime;
129+
ctx.include_error_details = true;
130+
131+
cosmos_client *client = NULL;
132+
133+
// First call - create client
134+
cosmos_error_code code = cosmos_client_create_with_key(&ctx, endpoint, key, &client);
135+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
136+
printf("First call failed with code: %d\n", code);
137+
cosmos_runtime_context_free(runtime);
138+
return TEST_FAIL;
139+
}
140+
printf("First call succeeded (client created)\n");
141+
142+
cosmos_database_client *database = NULL;
143+
144+
// Reuse context for second call - try to get a database client
145+
code = cosmos_client_database_client(&ctx, client, "nonexistent-db", &database);
146+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
147+
printf("Second call failed with code: %d (expected, just testing reuse)\n", code);
148+
// This is okay - we're testing context reuse, not that the operation succeeds
149+
} else {
150+
printf("Second call succeeded (database client retrieved)\n");
151+
cosmos_database_free(database);
152+
}
153+
154+
// Reuse context for third call - try again
155+
database = NULL;
156+
code = cosmos_client_database_client(&ctx, client, "another-nonexistent-db", &database);
157+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
158+
printf("Third call failed with code: %d (expected, just testing reuse)\n", code);
159+
} else {
160+
printf("Third call succeeded (database client retrieved)\n");
161+
cosmos_database_free(database);
162+
}
163+
164+
printf("Successfully reused call context for multiple operations\n");
165+
166+
cosmos_client_free(client);
167+
cosmos_runtime_context_free(runtime);
168+
return TEST_PASS;
169+
}
170+
171+
// Test 5: String memory management
172+
int test_string_memory_management() {
173+
printf("\n--- Test: string_memory_management ---\n");
174+
175+
const char *endpoint = getenv("AZURE_COSMOS_ENDPOINT");
176+
const char *key = getenv("AZURE_COSMOS_KEY");
177+
178+
if (!endpoint || !key) {
179+
printf("Skipping test - requires AZURE_COSMOS_ENDPOINT and AZURE_COSMOS_KEY\n");
180+
return TEST_PASS;
181+
}
182+
183+
time_t current_time = time(NULL);
184+
char database_name[64];
185+
snprintf(database_name, sizeof(database_name), "auto-test-db-str-mem-%ld", current_time);
186+
187+
cosmos_runtime_context *runtime = cosmos_runtime_context_create(NULL);
188+
if (!runtime) {
189+
printf("Failed to create runtime context\n");
190+
return TEST_FAIL;
191+
}
192+
193+
cosmos_call_context ctx;
194+
ctx.runtime_context = runtime;
195+
ctx.include_error_details = true;
196+
197+
cosmos_client *client = NULL;
198+
cosmos_database_client *database = NULL;
199+
cosmos_container_client *container = NULL;
200+
const char *read_json = NULL;
201+
int result = TEST_PASS;
202+
int database_created = 0;
203+
204+
// Create client
205+
cosmos_error_code code = cosmos_client_create_with_key(&ctx, endpoint, key, &client);
206+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
207+
printf("Failed to create client\n");
208+
result = TEST_FAIL;
209+
goto cleanup;
210+
}
211+
212+
// Create database
213+
code = cosmos_client_create_database(&ctx, client, database_name, &database);
214+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
215+
printf("Failed to create database\n");
216+
result = TEST_FAIL;
217+
goto cleanup;
218+
}
219+
database_created = 1;
220+
printf("Created database: %s\n", database_name);
221+
222+
// Create container
223+
code = cosmos_database_create_container(&ctx, database, "test-container", "/pk", &container);
224+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
225+
printf("Failed to create container\n");
226+
result = TEST_FAIL;
227+
goto cleanup;
228+
}
229+
printf("Created container\n");
230+
231+
// Create an item
232+
const char *json_data = "{\"id\":\"item1\",\"pk\":\"pk1\",\"value\":\"test\"}";
233+
code = cosmos_container_upsert_item(&ctx, container, "pk1", json_data);
234+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
235+
printf("Failed to upsert item\n");
236+
result = TEST_FAIL;
237+
goto cleanup;
238+
}
239+
printf("Upserted item\n");
240+
241+
// Read the item - this returns a string that must be freed
242+
code = cosmos_container_read_item(&ctx, container, "pk1", "item1", &read_json);
243+
if (code != COSMOS_ERROR_CODE_SUCCESS) {
244+
printf("Failed to read item\n");
245+
result = TEST_FAIL;
246+
goto cleanup;
247+
}
248+
printf("Read item: %s\n", read_json);
249+
250+
// Test freeing the string
251+
if (read_json) {
252+
cosmos_string_free(read_json);
253+
read_json = NULL;
254+
printf("Successfully freed JSON string\n");
255+
}
256+
257+
// Test freeing error details (trigger an error)
258+
code = cosmos_container_read_item(&ctx, container, "pk1", "nonexistent-item", &read_json);
259+
if (code == COSMOS_ERROR_CODE_NOT_FOUND) {
260+
printf("Got expected NOT_FOUND error\n");
261+
if (ctx.error.detail) {
262+
printf("Error detail present: %s\n", ctx.error.detail);
263+
cosmos_string_free(ctx.error.detail);
264+
printf("Successfully freed error detail string\n");
265+
}
266+
}
267+
268+
cleanup:
269+
if (database && database_created) {
270+
cosmos_database_delete(&ctx, database);
271+
}
272+
273+
if (container) {
274+
cosmos_container_free(container);
275+
}
276+
if (database) {
277+
cosmos_database_free(database);
278+
}
279+
if (client) {
280+
cosmos_client_free(client);
281+
}
282+
cosmos_runtime_context_free(runtime);
283+
284+
return result;
285+
}
286+
287+
int main() {
288+
printf("=== Test Suite 1: Context and Memory Management ===\n");
289+
290+
report_test("runtime_context_lifecycle", test_runtime_context_lifecycle() == TEST_PASS);
291+
report_test("call_context_stack_allocated", test_call_context_stack_allocated() == TEST_PASS);
292+
report_test("call_context_heap_allocated", test_call_context_heap_allocated() == TEST_PASS);
293+
report_test("call_context_reuse", test_call_context_reuse() == TEST_PASS);
294+
report_test("string_memory_management", test_string_memory_management() == TEST_PASS);
295+
296+
printf("\n=== Test Summary ===\n");
297+
printf("Tests run: %d\n", tests_run);
298+
printf("Tests passed: %d\n", tests_passed);
299+
printf("Tests failed: %d\n", tests_run - tests_passed);
300+
301+
if (tests_passed == tests_run) {
302+
printf("\n✓ All tests passed!\n");
303+
return 0;
304+
} else {
305+
printf("\n✗ Some tests failed\n");
306+
return 1;
307+
}
308+
}

0 commit comments

Comments
 (0)