Mercurial
view s3/tests/s3_uploader_test.c @ 279:b3b547563ec7
Add Google connector service and agent wiki
Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:22:36 -0700 |
| parents | 008ca7780c8a |
| children |
line wrap: on
line source
#include "s3/s3_uploader.h" #include <stdio.h> #include <stdlib.h> #include <string.h> // Simple .env parser static char *parse_env_value(const char *env_content, const char *key) { const char *pos = strstr(env_content, key); if (!pos) return NULL; pos += strlen(key); if (*pos != '=') return NULL; pos++; const char *end = pos; while (*end && *end != '\n' && *end != '\r') end++; size_t len = end - pos; char *value = malloc(len + 1); memcpy(value, pos, len); value[len] = '\0'; return value; } static char *load_file(const char *path) { FILE *f = fopen(path, "r"); if (!f) return NULL; fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); char *content = malloc(size + 1); fread(content, 1, size, f); content[size] = '\0'; fclose(f); return content; } int main(int argc, char **argv) { // Try to load .env file - check multiple locations for bazel runfiles char *env_content = load_file(".env"); if (!env_content) { env_content = load_file("zenbu/.env"); // bazel runfiles path } if (!env_content) { env_content = load_file("../.env"); } if (!env_content) { env_content = load_file("../../.env"); } char *access_key = NULL; char *secret_key = NULL; if (env_content) { access_key = parse_env_value(env_content, "AWS_MRJUNEJUNE_ACCESS_KEY"); secret_key = parse_env_value(env_content, "AWS_MRJUNEJUNE_SECRET_ACCESS_KEY"); free(env_content); } // Fall back to environment variables if (!access_key) access_key = getenv("AWS_ACCESS_KEY_ID") ? strdup(getenv("AWS_ACCESS_KEY_ID")) : NULL; if (!secret_key) secret_key = getenv("AWS_SECRET_ACCESS_KEY") ? strdup(getenv("AWS_SECRET_ACCESS_KEY")) : NULL; if (!access_key || !secret_key) { printf("Missing credentials. Set in .env file or environment:\n"); printf(" AWS_MRJUNEJUNE_ACCESS_KEY / AWS_ACCESS_KEY_ID\n"); printf(" AWS_MRJUNEJUNE_SECRET_ACCESS_KEY / AWS_SECRET_ACCESS_KEY\n"); return 1; } S3_Config config = { .access_key_id = access_key, .secret_access_key = secret_key, .region = "us-west-2", .bucket = "mrjunejune", .endpoint = NULL, .use_path_style = FALSE }; printf("S3 Uploader Test\n"); printf("================\n"); printf("Region: %s\n", config.region); printf("Bucket: %s\n", config.bucket); printf("\n"); // Test 1: Upload string data printf("Test 1: Uploading string data...\n"); const char *test_data = "Hello from S3 uploader test!"; S3_Result result = S3_Upload_Data(&config, (const uint8 *)test_data, strlen(test_data), "test/hello.txt", "text/plain"); if (result.success) { printf(" SUCCESS! ETag: %s\n", result.etag ? result.etag : "(none)"); } else { printf(" FAILED! Status: %d, Error: %s\n", result.status_code, result.error_message ? result.error_message : "(unknown)"); } S3_Result_Destroy(&result); // Test 2: Content type detection printf("\nTest 2: Content type detection...\n"); printf(" .html -> %s\n", S3_Guess_Content_Type("page.html")); printf(" .png -> %s\n", S3_Guess_Content_Type("image.png")); printf(" .json -> %s\n", S3_Guess_Content_Type("data.json")); printf(" .xyz -> %s\n", S3_Guess_Content_Type("unknown.xyz")); // Test 3: Generate presigned PUT URL printf("\nTest 3: Generating presigned PUT URL...\n"); S3_Presigned_URL put_url = S3_Presign_Put(&config, "uploads/client-upload.png", "image/png", 3600); // 1 hour if (put_url.success) { printf(" SUCCESS!\n"); printf(" URL: %s\n", put_url.url); printf("\n Client can upload with:\n"); printf(" curl -X PUT -H \"Content-Type: image/png\" --data-binary @file.png \"$URL\"\n"); } else { printf(" FAILED! Error: %s\n", put_url.error_message ? put_url.error_message : "(unknown)"); } S3_Presigned_URL_Destroy(&put_url); // Test 4: Generate presigned GET URL printf("\nTest 4: Generating presigned GET URL...\n"); S3_Presigned_URL get_url = S3_Presign_Get(&config, "uploads/client-upload.png", 3600); // 1 hour if (get_url.success) { printf(" SUCCESS!\n"); printf(" URL: %s\n", get_url.url); printf("\n Client can download with:\n"); printf(" curl \"$URL\" -o file.png\n"); } else { printf(" FAILED! Error: %s\n", get_url.error_message ? get_url.error_message : "(unknown)"); } S3_Presigned_URL_Destroy(&get_url); // Test 5: Upload file (if provided as argument) if (argc >= 3) { printf("\nTest 5: Uploading file...\n"); printf(" Local: %s\n", argv[1]); printf(" S3 Key: %s\n", argv[2]); result = S3_Upload_File(&config, argv[1], argv[2]); if (result.success) { printf(" SUCCESS! ETag: %s\n", result.etag ? result.etag : "(none)"); } else { printf(" FAILED! Status: %d, Error: %s\n", result.status_code, result.error_message ? result.error_message : "(unknown)"); } S3_Result_Destroy(&result); } else { printf("\nTest 5: Skipped (no file path provided)\n"); printf(" Usage: %s <local_file> <s3_key>\n", argv[0]); } printf("\nDone!\n"); free(access_key); free(secret_key); return 0; }