Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions core/tests/unit/test_cache_strict_equality.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ typedef struct test_git_repo_port {
gm_git_reference_tip_t glob_tip;
} test_git_repo_port_t;

/**
* Provide the repository path for the requested kind (test stub).
*
* This stub does not implement path resolution and always returns an error
* indicating the operation is not implemented.
*
* @returns A gm_result_void_t error result containing `GM_ERR_NOT_IMPLEMENTED`.
*/
static gm_result_void_t stub_repository_path(void *self,
gm_git_repository_path_kind_t kind,
char *out_buffer,
Expand All @@ -36,6 +44,14 @@ static gm_result_void_t stub_repository_path(void *self,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Stub implementation for retrieving the current HEAD branch name used in tests.
*
* @param self Opaque pointer to the repository port instance (ignored).
* @param out_name Buffer to receive the branch name (ignored).
* @param out_name_size Size of the out_name buffer (ignored).
* @returns A gm_result_void_t representing the `GM_ERR_NOT_IMPLEMENTED` error.
*/
static gm_result_void_t stub_head_branch(void *self, char *out_name,
size_t out_name_size) {
(void)self;
Expand All @@ -44,6 +60,14 @@ static gm_result_void_t stub_head_branch(void *self, char *out_name,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Test stub for building a tree that always reports the operation as not implemented.
*
* This function does not construct or modify any tree and exists only for testing;
* it always fails with a "not implemented" error.
*
* @returns An error result with `GM_ERR_NOT_IMPLEMENTED`.
*/
static gm_result_void_t stub_build_tree(void *self, const char *dir_path,
gm_oid_t *out_tree_oid) {
(void)self;
Expand All @@ -52,6 +76,18 @@ static gm_result_void_t stub_build_tree(void *self, const char *dir_path,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Populate the output reference tip based on the provided reference name.
*
* If ref_name starts with GM_CACHE_REF_PREFIX, copies the stub's cache_tip to out_tip.
* If ref_name starts with GITMIND_EDGES_REF_PREFIX, copies the current journal tip
* (stub->journal_tips[stub->journal_tip_index]) to out_tip and advances journal_tip_index
* by one unless already at the last tip. For any other ref_name, sets out_tip to an all-zero tip.
*
* @param ref_name The reference name used to select which tip to return.
* @param out_tip Pointer to receive the selected or zeroed gm_git_reference_tip_t.
* @returns `GM_OK` on success; `GM_ERR_INVALID_ARGUMENT` if ref_name or out_tip is NULL.
*/
static gm_result_void_t reference_tip(void *self, const char *ref_name,
gm_git_reference_tip_t *out_tip) {
test_git_repo_port_t *stub = (test_git_repo_port_t *)self;
Expand Down Expand Up @@ -87,6 +123,17 @@ static gm_result_void_t reference_tip(void *self, const char *ref_name,
return gm_ok_void();
}

/**
* Retrieve the latest reference tip matching a glob pattern from the test stub.
*
* The provided pattern is validated for non-NULL but not inspected; the function
* always returns the stub's preset glob_tip into `out_tip`.
*
* @param pattern Glob pattern to match (validated for non-NULL; otherwise ignored).
* @param out_tip Output pointer that receives the latest matching reference tip.
* @returns `gm_ok_void()` on success; `gm_err_void(GM_ERR_INVALID_ARGUMENT, ...)`
* if `pattern` or `out_tip` is NULL.
*/
static gm_result_void_t reference_glob_latest(void *self, const char *pattern,
gm_git_reference_tip_t *out_tip) {
test_git_repo_port_t *stub = (test_git_repo_port_t *)self;
Expand All @@ -99,6 +146,15 @@ static gm_result_void_t reference_glob_latest(void *self, const char *pattern,
return gm_ok_void();
}

/**
* Stub implementation of reading a blob at a commit path that always fails.
*
* If provided, sets `*out_data` to NULL and `*out_size` to 0 before returning.
*
* @param out_data If non-NULL, receives NULL to indicate no data was produced.
* @param out_size If non-NULL, receives 0 to indicate zero bytes.
* @returns An error result indicating the operation is not implemented.
*/
static gm_result_void_t stub_commit_read_blob(void *self,
const gm_oid_t *commit_oid,
const char *path,
Expand All @@ -116,12 +172,25 @@ static gm_result_void_t stub_commit_read_blob(void *self,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Free memory backing a blob buffer.
*
* @param data Pointer to the blob buffer to free.
* @param size Size of the blob buffer in bytes (unused by this implementation).
*/
static void blob_dispose(void *self, uint8_t *data, size_t size) {
(void)self;
(void)size;
free(data);
}

/**
* Stub implementation that attempts to read a commit message but always fails and clears the output pointer.
*
* @param commit_oid Commit OID to read; ignored by this test stub.
* @param out_message Pointer to receive the commit message; if non-NULL, set to NULL.
* @returns An error indicating the operation is not implemented (`GM_ERR_NOT_IMPLEMENTED`) wrapped in a `gm_result_void_t`.
*/
static gm_result_void_t stub_commit_read_message(void *self,
const gm_oid_t *commit_oid,
char **out_message) {
Expand All @@ -133,11 +202,21 @@ static gm_result_void_t stub_commit_read_message(void *self,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Free a heap-allocated commit message.
*
* @param message Pointer to a heap-allocated NUL-terminated commit message to free; may be NULL.
*/
static void stub_commit_message_dispose(void *self, char *message) {
(void)self;
free(message);
}

/**
* Test stub for walking commits that always reports the operation as not implemented.
*
* @returns An error result with `GM_ERR_NOT_IMPLEMENTED`.
*/
static gm_result_void_t stub_walk_commits(void *self, const char *ref_name,
gm_git_commit_visit_cb visit_callback,
void *userdata) {
Expand All @@ -148,6 +227,17 @@ static gm_result_void_t stub_walk_commits(void *self, const char *ref_name,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Stub implementation of commit tree size retrieval for tests.
*
* If `out_size_bytes` is non-NULL, it is set to 0. The function always
* returns an error result indicating the operation is not implemented.
*
* @param self Unused stub instance pointer.
* @param commit_oid Unused commit OID.
* @param out_size_bytes If non-NULL, receives 0.
* @returns A gm_result_void_t containing `GM_ERR_NOT_IMPLEMENTED`.
*/
static gm_result_void_t stub_commit_tree_size(void *self,
const gm_oid_t *commit_oid,
uint64_t *out_size_bytes) {
Expand All @@ -159,6 +249,16 @@ static gm_result_void_t stub_commit_tree_size(void *self,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Test stub for creating a commit in the repository port.
*
* This implementation does not create a commit and always returns a not-implemented error.
*
* @param self Pointer to the repository port instance (unused).
* @param spec Specification of the commit to create (unused).
* @param out_commit_oid Output OID for the created commit (unused).
* @returns A gm_result_void_t representing `GM_ERR_NOT_IMPLEMENTED`.
*/
static gm_result_void_t stub_commit_create(void *self,
const gm_git_commit_spec_t *spec,
gm_oid_t *out_commit_oid) {
Expand All @@ -168,13 +268,26 @@ static gm_result_void_t stub_commit_create(void *self,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Stub implementation of a reference update used by tests that always reports not implemented.
*
* @returns A `gm_result_void_t` representing an error with code `GM_ERR_NOT_IMPLEMENTED` and message "test stub".
*/
static gm_result_void_t stub_reference_update(
void *self, const gm_git_reference_update_spec_t *spec) {
(void)self;
(void)spec;
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Stub that would resolve the blob OID for `path` at HEAD in test repository ports.
*
* @param self Pointer to the repository port instance (unused).
* @param path Path of the blob to resolve.
* @param out_blob_oid Output pointer to receive the blob OID when resolution succeeds.
* @returns A `gm_result_void_t` error value indicating not implemented (`GM_ERR_NOT_IMPLEMENTED`) for this test stub.
*/
static gm_result_void_t stub_resolve_blob_at_head(void *self, const char *path,
gm_oid_t *out_blob_oid) {
(void)self;
Expand All @@ -183,6 +296,11 @@ static gm_result_void_t stub_resolve_blob_at_head(void *self, const char *path,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Test stub that intentionally does not resolve a blob at a specific commit.
*
* @returns An error result with code GM_ERR_NOT_IMPLEMENTED indicating the operation is not implemented in the test stub.
*/
static gm_result_void_t stub_resolve_blob_at_commit(void *self,
const gm_oid_t *commit_oid,
const char *path,
Expand All @@ -194,6 +312,16 @@ static gm_result_void_t stub_resolve_blob_at_commit(void *self,
return gm_err_void(GM_ERROR(GM_ERR_NOT_IMPLEMENTED, "test stub"));
}

/**
* Stub that reports a commit has zero parents and indicates the operation is not implemented.
*
* If `out_parent_count` is non-NULL, it is set to 0 to indicate no parents.
*
* @param self Opaque repository port instance (unused).
* @param commit_oid OID of the commit to query (unused).
* @param out_parent_count Pointer to receive the parent count; set to 0 if non-NULL.
* @returns An error result indicating the function is not implemented (`GM_ERR_NOT_IMPLEMENTED`).
*/
static gm_result_void_t stub_commit_parent_count(void *self,
const gm_oid_t *commit_oid,
size_t *out_parent_count) {
Expand Down Expand Up @@ -224,17 +352,40 @@ static const gm_git_repository_port_vtbl_t TEST_PORT_VTBL = {
.commit_parent_count = stub_commit_parent_count,
};

/**
* Prepare a test_git_repo_port_t for use by zeroing it and configuring its repository port vtable and self pointer.
* @param stub Pointer to the test stub to initialize.
*/
static void init_stub(test_git_repo_port_t *stub) {
gm_memset_safe(stub, sizeof(*stub), 0, sizeof(*stub));
stub->port.vtbl = &TEST_PORT_VTBL;
stub->port.self = stub;
}

/**
* Initialize `oid` from a hexadecimal string and abort on failure.
*
* @param oid Pointer to the OID to be populated.
* @param hex NUL-terminated hexadecimal string representation of the OID.
*/
static void set_oid_from_hex(gm_oid_t *oid, const char *hex) {
int rc = gm_oid_from_hex(oid, hex);
assert(rc == GM_OK);
}

/**
* Initialize a git reference tip structure with the given OID hex, commit time, and flags.
*
* Populates the provided gm_git_reference_tip_t by zeroing it and setting has_target and commit_time.
* If `zero_binary` is false and `hex` is non-NULL, the binary OID is parsed from `hex` and stored.
* If `hex` is non-NULL, its characters are copied into `tip->oid_hex` and NUL-terminated (truncated if necessary).
*
* @param tip Pointer to the tip structure to initialize.
* @param hex Hexadecimal string representation of the OID to store or copy; may be NULL.
* @param commit_time Commit timestamp to assign to the tip.
* @param has_target Whether the tip has a target reference.
* @param zero_binary If true, do not populate the binary OID even if `hex` is provided.
*/
static void set_tip(gm_git_reference_tip_t *tip, const char *hex,
uint64_t commit_time, bool has_target, bool zero_binary) {
gm_memset_safe(tip, sizeof(*tip), 0, sizeof(*tip));
Expand All @@ -253,17 +404,44 @@ static void set_tip(gm_git_reference_tip_t *tip, const char *hex,
}
}

/**
* Fill a buffer with a repeated character and ensure null-termination.
*
* Writes `digit` into each of the first `buffer_len - 1` bytes and sets the
* final byte to the NUL terminator (`'\0'`).
*
* @param buffer Pointer to the destination buffer.
* @param buffer_len Total size of `buffer` in bytes; must be at least 1.
* @param digit Character to repeat throughout the buffer (except the terminator).
*/
static void fill_hex(char *buffer, size_t buffer_len, char digit) {
for (size_t i = 0; i + 1U < buffer_len; ++i) {
buffer[i] = digit;
}
buffer[buffer_len - 1U] = '\0';
}

/**
* Reset the journal tip sequence index to the beginning.
*
* This sets the test repository port's journal_tip_index to 0 so subsequent
* journal tip retrievals start from the first entry.
*
* @param stub Test repository port whose journal sequence will be reset.
*/
static void reset_journal_sequence(test_git_repo_port_t *stub) {
stub->journal_tip_index = 0U;
}

/**
* Run unit tests that validate strict equality behavior of the cache check.
*
* Executes four scenarios that exercise gm_cache_is_stale with combinations of
* binary OID presence and legacy hex values to verify OID-first equality and
* hex-string fallback behavior.
*
* @returns 0 on success; a non-zero result (via failed assertion or abort) on failure.
*/
int main(void) {
printf("test_cache_strict_equality... ");

Expand Down
24 changes: 24 additions & 0 deletions core/tests/unit/test_journal_mixed_cbor.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ typedef struct {
gm_edge_attributed_t last;
} attr_ctx_t;

/**
* Capture a basic edge into a basic_ctx_t by copying the provided edge and
* incrementing the context's count.
*
* @param edge Pointer to the basic edge to capture.
* @param ud Pointer to a basic_ctx_t where the edge will be stored (last)
* and the count incremented.
* @returns `GM_OK` on success, `GM_ERR_INVALID_ARGUMENT` if `edge` or `ud` is NULL,
* or another `GM_*` error code propagated from the copy operation.
*/
static int capture_basic_cb(const gm_edge_t *edge, void *ud) {
if (edge == NULL || ud == NULL) {
return GM_ERR_INVALID_ARGUMENT;
Expand All @@ -43,6 +53,13 @@ static int capture_basic_cb(const gm_edge_t *edge, void *ud) {
return GM_OK;
}

/**
* Capture an attributed edge by copying it into the provided context and incrementing the count.
*
* @param edge Pointer to the attributed edge to capture; must not be NULL.
* @param ud Pointer to an attr_ctx_t that will receive the captured edge and have its count incremented; must not be NULL.
* @returns `GM_OK` on success, `GM_ERR_INVALID_ARGUMENT` if `edge` or `ud` is NULL, or an error code returned from the underlying copy operation.
*/
static int capture_attr_cb(const gm_edge_attributed_t *edge, void *ud) {
if (edge == NULL || ud == NULL) {
return GM_ERR_INVALID_ARGUMENT;
Expand All @@ -57,6 +74,13 @@ static int capture_attr_cb(const gm_edge_attributed_t *edge, void *ud) {
return GM_OK;
}

/**
* Run the mixed-CBOR journal integration test: create a temporary Git repository,
* write a commit containing one basic and one attributed CBOR-encoded edge payload,
* read them back, and verify their source/target OIDs match the generated values.
*
* @returns `0` on success, non-zero on failure.
*/
int main(void) {
printf("test_journal_mixed_cbor... ");
git_libgit2_init();
Expand Down
Loading