feat: publish Dever core with project scaffolding and versioned AI skills
This commit is contained in:
1 parent
70fa73cdc2
commit
ac458ffa7f
960 files changed
+221319
-1163
No files matched your search
@@ -0,0 +1,245 @@
|
||||
/* Database ABI ownership without settings, pools or database connections.
|
||||
* The existing managed-driver supplies warm 1 + 64 and the strict ledger. */
|
||||
#include "runtime.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t kind;
|
||||
void *message;
|
||||
void *cause;
|
||||
} Fault;
|
||||
|
||||
typedef struct {
|
||||
uint8_t present;
|
||||
void *text;
|
||||
} OptionalText;
|
||||
|
||||
static unsigned packs;
|
||||
static unsigned moves;
|
||||
static unsigned drops;
|
||||
|
||||
static void release_buffer(DeverRtBuffer *buffer) {
|
||||
dever_rt_v1_buffer_free(buffer->ptr, buffer->len);
|
||||
*buffer = (DeverRtBuffer){0};
|
||||
}
|
||||
|
||||
static int buffer_is(const DeverRtBuffer *buffer, const char *expected) {
|
||||
size_t length = strlen(expected);
|
||||
return buffer->ptr && buffer->len == length &&
|
||||
memcmp(buffer->ptr, expected, length) == 0;
|
||||
}
|
||||
|
||||
static int text_is(const void *text, const char *expected) {
|
||||
DeverRtBuffer buffer = {0};
|
||||
uint32_t status = dever_rt_v1_text_export(text, &buffer);
|
||||
int matches = status == 0 && buffer_is(&buffer, expected);
|
||||
release_buffer(&buffer);
|
||||
return matches;
|
||||
}
|
||||
|
||||
static int new_text(const char *text, void **out) {
|
||||
DeverRtBuffer buffer = {0};
|
||||
uint32_t status = dever_rt_v1_text_new(
|
||||
(const uint8_t *)text, strlen(text), out, &buffer);
|
||||
release_buffer(&buffer);
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
static void move_fault(void *source, void *destination) {
|
||||
*(Fault *)destination = *(Fault *)source;
|
||||
*(Fault *)source = (Fault){0};
|
||||
++moves;
|
||||
}
|
||||
|
||||
static void drop_fault(void *value) {
|
||||
Fault *fault = value;
|
||||
dever_rt_v1_text_release(fault->message);
|
||||
dever_rt_v1_text_release(fault->cause);
|
||||
*fault = (Fault){0};
|
||||
++drops;
|
||||
}
|
||||
|
||||
static void pack_fault(uint32_t kind, const void *message, void *out) {
|
||||
*(Fault *)out = (Fault){kind, dever_rt_v1_text_retain(message), NULL};
|
||||
++packs;
|
||||
}
|
||||
|
||||
static void append_cause(void *value, const void *message) {
|
||||
dever_rt_v1_db_cause_append(&((Fault *)value)->cause, message);
|
||||
}
|
||||
|
||||
static const DeverRtOwnedType fault_type = {
|
||||
sizeof(Fault), _Alignof(Fault), move_fault, drop_fault, 1
|
||||
};
|
||||
static const DeverRtDbError errors = {&fault_type, pack_fault, append_cause};
|
||||
|
||||
static void clone_optional(const void *source, void *destination) {
|
||||
const OptionalText *from = source;
|
||||
*(OptionalText *)destination = (OptionalText){
|
||||
from->present, from->present ? dever_rt_v1_text_retain(from->text) : NULL
|
||||
};
|
||||
}
|
||||
|
||||
static void drop_optional(void *value) {
|
||||
OptionalText *text = value;
|
||||
if (text->present) dever_rt_v1_text_release(text->text);
|
||||
*text = (OptionalText){0};
|
||||
}
|
||||
|
||||
static uint8_t equal_optional(const void *left, const void *right) {
|
||||
const OptionalText *a = left;
|
||||
const OptionalText *b = right;
|
||||
return a->present == b->present &&
|
||||
(!a->present || dever_rt_v1_text_equal(a->text, b->text));
|
||||
}
|
||||
|
||||
static const DeverRtType optional_type = {
|
||||
sizeof(OptionalText), _Alignof(OptionalText),
|
||||
clone_optional, drop_optional, equal_optional, NULL
|
||||
};
|
||||
|
||||
/* Preserve cleanup on an assertion failure so the first diagnostic identifies
|
||||
* the broken contract, not a second error caused by the test's own resources. */
|
||||
#define CHECK(condition) do { if (!(condition)) { result = __LINE__; goto cleanup; } } while (0)
|
||||
|
||||
static int error_kinds(void) {
|
||||
int result = 0;
|
||||
DeverRtBuffer buffer = {0};
|
||||
Fault fault = {0};
|
||||
void *message = NULL;
|
||||
unsigned before_packs = packs;
|
||||
unsigned before_moves = moves;
|
||||
unsigned before_drops = drops;
|
||||
for (uint32_t kind = 0; kind < 10; ++kind) {
|
||||
CHECK(new_text("original database diagnostic: \xe6\x95\xb0\xe6\x8d\xae", &message));
|
||||
CHECK(dever_rt_v1_db_error(kind, message, &errors, &fault, &buffer) == 1);
|
||||
CHECK(buffer.ptr == NULL && buffer.len == 0 && fault.kind == kind);
|
||||
dever_rt_v1_text_release(message);
|
||||
message = NULL;
|
||||
/* pack's borrowed handle is retainable after the bridge returns. */
|
||||
CHECK(text_is(fault.message, "original database diagnostic: \xe6\x95\xb0\xe6\x8d\xae"));
|
||||
CHECK(new_text("rollback failed", &message));
|
||||
append_cause(&fault, message);
|
||||
append_cause(&fault, message);
|
||||
dever_rt_v1_text_release(message);
|
||||
message = NULL;
|
||||
CHECK(fault.kind == kind && text_is(fault.cause,
|
||||
"caused by: rollback failed; caused by: rollback failed"));
|
||||
drop_fault(&fault);
|
||||
}
|
||||
CHECK(packs == before_packs + 10 && moves == before_moves + 10 &&
|
||||
drops == before_drops + 10);
|
||||
cleanup:
|
||||
dever_rt_v1_text_release(message);
|
||||
if (fault.message || fault.cause) drop_fault(&fault);
|
||||
release_buffer(&buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int related_owners(void) {
|
||||
int result = 0;
|
||||
DeverRtBuffer buffer = {0};
|
||||
OptionalText source = {1, NULL}, extracted = {0}, absent = {0};
|
||||
void *related = NULL, *alias = NULL, *loaded_null = NULL, *second_null = NULL;
|
||||
CHECK(new_text("related-owned", &source.text));
|
||||
CHECK(dever_rt_v1_db_related_new(&optional_type, &source, &related, &buffer) == 0);
|
||||
alias = dever_rt_v1_db_related_retain(related);
|
||||
drop_optional(&source);
|
||||
dever_rt_v1_db_related_release(related);
|
||||
related = NULL;
|
||||
CHECK(dever_rt_v1_db_related_get(alias, &extracted, &buffer) == 0);
|
||||
dever_rt_v1_db_related_release(alias);
|
||||
alias = NULL;
|
||||
CHECK(extracted.present == 1 && text_is(extracted.text, "related-owned"));
|
||||
CHECK(dever_rt_v1_db_related_new(&optional_type, &absent, &loaded_null, &buffer) == 0);
|
||||
CHECK(dever_rt_v1_db_related_new(&optional_type, &absent, &second_null, &buffer) == 0);
|
||||
CHECK(loaded_null != NULL && dever_rt_v1_db_related_equal(loaded_null, second_null) == 1);
|
||||
CHECK(dever_rt_v1_db_related_equal(NULL, loaded_null) == 0);
|
||||
CHECK(dever_rt_v1_db_related_equal(NULL, NULL) == 1);
|
||||
drop_optional(&extracted);
|
||||
CHECK(dever_rt_v1_db_related_get(loaded_null, &extracted, &buffer) == 0);
|
||||
CHECK(extracted.present == 0 && extracted.text == NULL);
|
||||
cleanup:
|
||||
drop_optional(&source);
|
||||
drop_optional(&extracted);
|
||||
dever_rt_v1_db_related_release(related);
|
||||
dever_rt_v1_db_related_release(alias);
|
||||
dever_rt_v1_db_related_release(loaded_null);
|
||||
dever_rt_v1_db_related_release(second_null);
|
||||
release_buffer(&buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int invalid_destinations(void) {
|
||||
int result = 0;
|
||||
DeverRtBuffer buffer = {0};
|
||||
Fault fault = {37, NULL, NULL};
|
||||
int64_t output = 41;
|
||||
unsigned before = packs;
|
||||
CHECK(dever_rt_v1_db_cursor_size(0, 7, NULL, &errors, &fault, &buffer) == 2);
|
||||
CHECK(buffer_is(&buffer, "invalid ABI output pointer") && packs == before && fault.kind == 37);
|
||||
release_buffer(&buffer);
|
||||
_Alignas(int64_t) unsigned char storage[sizeof(int64_t) + 1];
|
||||
memset(storage, 53, sizeof(storage));
|
||||
CHECK(dever_rt_v1_db_stream_capacity(0, 7, (int64_t *)(storage + 1), &errors, &fault, &buffer) == 2);
|
||||
CHECK(packs == before && fault.kind == 37);
|
||||
for (size_t i = 0; i < sizeof(storage); ++i) CHECK(storage[i] == 53);
|
||||
release_buffer(&buffer);
|
||||
CHECK(dever_rt_v1_db_cursor_size(0, 7, &output, &errors, NULL, &buffer) == 2);
|
||||
CHECK(output == 41 && packs == before && buffer_is(&buffer, "invalid database fault output"));
|
||||
release_buffer(&buffer);
|
||||
CHECK(dever_rt_v1_db_cursor_size(0, 7, &output, &errors, &fault, &buffer) == 1);
|
||||
CHECK(output == 41 && fault.kind == 8 && text_is(fault.message, "cursor size must be between 1 and 7"));
|
||||
drop_fault(&fault);
|
||||
CHECK(dever_rt_v1_db_stream_capacity(0, 7, &output, &errors, &fault, &buffer) == 1);
|
||||
CHECK(output == 41 && fault.kind == 8 && text_is(fault.message, "stream buffer size must be between 1 and 7"));
|
||||
drop_fault(&fault);
|
||||
CHECK(dever_rt_v1_db_cursor_size(3, 7, &output, &errors, &fault, &buffer) == 0 && output == 3);
|
||||
CHECK(packs == before + 2 && buffer.ptr == NULL && buffer.len == 0);
|
||||
cleanup:
|
||||
if (fault.message || fault.cause) drop_fault(&fault);
|
||||
release_buffer(&buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int invalid_constructors(void) {
|
||||
int result = 0;
|
||||
DeverRtBuffer buffer = {0};
|
||||
Fault primary = {6, NULL, NULL};
|
||||
DeverRtAsyncOp *operation = NULL;
|
||||
void *session = (void *)(uintptr_t)47;
|
||||
unsigned before_moves = moves, before_drops = drops;
|
||||
CHECK(new_text("primary-owned", &primary.message));
|
||||
operation = dever_rt_v1_db_rollback_take(NULL, &primary, &fault_type, &errors, &buffer);
|
||||
CHECK(operation == NULL && buffer_is(&buffer, "invalid ABI handle"));
|
||||
CHECK(moves == before_moves && drops == before_drops && primary.kind == 6 && text_is(primary.message, "primary-owned"));
|
||||
release_buffer(&buffer);
|
||||
|
||||
const DeverRtDbBinding bad_flag = {NULL, {(const uint8_t *)"fixture", 7}, 2};
|
||||
CHECK(dever_rt_v1_db_session_new(&bad_flag, 1, NULL, 0, NULL, &buffer) == 2);
|
||||
CHECK(buffer_is(&buffer, "invalid ABI output pointer"));
|
||||
release_buffer(&buffer);
|
||||
/* Metadata rejects before looking for config/setting.json or opening pools. */
|
||||
CHECK(dever_rt_v1_db_session_new(&bad_flag, 1, NULL, 0, &session, &buffer) == 2);
|
||||
CHECK(session == (void *)(uintptr_t)47 && buffer_is(&buffer, "invalid database ABI boolean"));
|
||||
release_buffer(&buffer);
|
||||
_Alignas(DeverRtDbBinding) unsigned char unaligned[sizeof(DeverRtDbBinding) + 1];
|
||||
CHECK(dever_rt_v1_db_session_new((const DeverRtDbBinding *)(unaligned + 1), 1, NULL, 0, &session, &buffer) == 2);
|
||||
CHECK(session == (void *)(uintptr_t)47 && buffer_is(&buffer, "invalid database ABI array"));
|
||||
cleanup:
|
||||
dever_rt_v1_async_op_release(operation);
|
||||
drop_fault(&primary);
|
||||
release_buffer(&buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t dever_test_run(void) {
|
||||
packs = moves = drops = 0;
|
||||
int result = error_kinds();
|
||||
if (result == 0) result = related_owners();
|
||||
if (result == 0) result = invalid_destinations();
|
||||
if (result == 0) result = invalid_constructors();
|
||||
return result;
|
||||
}
|
||||
Reference in new issue
Block a user