feat(controller-peers-env-fallback): add the shared "which candidate is me" lookup (task 1.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7328b06c53
commit
d4858e1fe9
4 changed files with 131 additions and 1 deletions
|
|
@ -65,6 +65,20 @@ const char* xce_controller_peers_env(void)
|
|||
return (v && v[0] != '\0') ? v : NULL;
|
||||
}
|
||||
|
||||
int xce_peers_find_identity(const xce_cluster_config_t* cfg, const char* name)
|
||||
{
|
||||
if (!cfg || !name)
|
||||
return -1;
|
||||
for (int i = 0; i < cfg->candidates_count; i++) {
|
||||
const char* key = cfg->candidates[i].name[0]
|
||||
? cfg->candidates[i].name
|
||||
: cfg->candidates[i].hostname;
|
||||
if (strncmp(key, name, XCE_MAXNAME_LEN - 1) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ── Test seam ─────────────────────────────────────────────────── */
|
||||
|
||||
static xce_connect_fn_t s_connect_fn = NULL;
|
||||
|
|
|
|||
|
|
@ -326,6 +326,100 @@ static void test_peers_env_nonempty_returned_unchanged(void)
|
|||
printf("test_peers_env_nonempty_returned_unchanged: PASS\n");
|
||||
}
|
||||
|
||||
/* ── xce_peers_find_identity() ──────────────────────────────────── */
|
||||
|
||||
/* Fill candidate i of cfg directly: name may be "" (unnamed entry),
|
||||
* hostname may be "" (only reachable by filling the struct by hand). */
|
||||
static void set_candidate(xce_cluster_config_t* cfg, int i, const char* name,
|
||||
const char* hostname, int port)
|
||||
{
|
||||
snprintf(cfg->candidates[i].name, XCE_MAXNAME_LEN, "%s", name);
|
||||
snprintf(cfg->candidates[i].hostname, XCE_MAXHOSTNAME_LEN, "%s",
|
||||
hostname);
|
||||
cfg->candidates[i].port = port;
|
||||
}
|
||||
|
||||
/* Req 1.6: a named candidate is found by its name. */
|
||||
static void test_find_identity_named_match(void)
|
||||
{
|
||||
xce_cluster_config_t cfg = {0};
|
||||
set_candidate(&cfg, 0, "c1", "localhost", 9991);
|
||||
set_candidate(&cfg, 1, "c2", "localhost", 9992);
|
||||
set_candidate(&cfg, 2, "c3", "localhost", 9993);
|
||||
cfg.candidates_count = 3;
|
||||
TEST_ASSERT_EQUAL_INT(1, xce_peers_find_identity(&cfg, "c2"));
|
||||
printf("test_find_identity_named_match: PASS\n");
|
||||
}
|
||||
|
||||
/* Req 1.6: an unnamed candidate is found by its hostname. */
|
||||
static void test_find_identity_unnamed_matched_by_hostname(void)
|
||||
{
|
||||
xce_cluster_config_t cfg = {0};
|
||||
set_candidate(&cfg, 0, "", "node1", 9990);
|
||||
set_candidate(&cfg, 1, "", "node2", 9990);
|
||||
cfg.candidates_count = 2;
|
||||
TEST_ASSERT_EQUAL_INT(1, xce_peers_find_identity(&cfg, "node2"));
|
||||
printf("test_find_identity_unnamed_matched_by_hostname: PASS\n");
|
||||
}
|
||||
|
||||
/* Req 1.6: a named candidate's key is its name only -- its hostname
|
||||
* does not identify it. */
|
||||
static void test_find_identity_named_not_matched_by_hostname(void)
|
||||
{
|
||||
xce_cluster_config_t cfg = {0};
|
||||
set_candidate(&cfg, 0, "c1", "node1", 9991);
|
||||
set_candidate(&cfg, 1, "c2", "node2", 9992);
|
||||
cfg.candidates_count = 2;
|
||||
TEST_ASSERT_EQUAL_INT(-1, xce_peers_find_identity(&cfg, "node2"));
|
||||
printf("test_find_identity_named_not_matched_by_hostname: PASS\n");
|
||||
}
|
||||
|
||||
/* Req 1.6: no candidate matches -> -1 (no default applied). */
|
||||
static void test_find_identity_no_match(void)
|
||||
{
|
||||
xce_cluster_config_t cfg = {0};
|
||||
set_candidate(&cfg, 0, "c1", "localhost", 9991);
|
||||
set_candidate(&cfg, 1, "", "node2", 9992);
|
||||
cfg.candidates_count = 2;
|
||||
TEST_ASSERT_EQUAL_INT(-1, xce_peers_find_identity(&cfg, "c9"));
|
||||
printf("test_find_identity_no_match: PASS\n");
|
||||
}
|
||||
|
||||
/* Req 1.6: the first of duplicate names wins (not the last). */
|
||||
static void test_find_identity_first_duplicate_wins(void)
|
||||
{
|
||||
xce_cluster_config_t cfg = {0};
|
||||
set_candidate(&cfg, 0, "c0", "localhost", 9990);
|
||||
set_candidate(&cfg, 1, "dup", "localhost", 9991);
|
||||
set_candidate(&cfg, 2, "dup", "localhost", 9992);
|
||||
cfg.candidates_count = 3;
|
||||
TEST_ASSERT_EQUAL_INT(1, xce_peers_find_identity(&cfg, "dup"));
|
||||
printf("test_find_identity_first_duplicate_wins: PASS\n");
|
||||
}
|
||||
|
||||
/* Req 1.6: no name given -> -1, even against an entry with empty keys. */
|
||||
static void test_find_identity_null_name(void)
|
||||
{
|
||||
xce_cluster_config_t cfg = {0};
|
||||
set_candidate(&cfg, 0, "c1", "localhost", 9991);
|
||||
set_candidate(&cfg, 1, "", "", 9992);
|
||||
cfg.candidates_count = 2;
|
||||
TEST_ASSERT_EQUAL_INT(-1, xce_peers_find_identity(&cfg, NULL));
|
||||
printf("test_find_identity_null_name: PASS\n");
|
||||
}
|
||||
|
||||
/* Req 1.6: an empty name is compared like any other, so it matches an
|
||||
* unnamed empty-hostname entry exactly as the controller's loops do. */
|
||||
static void test_find_identity_empty_name_matches_empty_hostname(void)
|
||||
{
|
||||
xce_cluster_config_t cfg = {0};
|
||||
set_candidate(&cfg, 0, "c1", "localhost", 9991);
|
||||
set_candidate(&cfg, 1, "", "", 9992);
|
||||
cfg.candidates_count = 2;
|
||||
TEST_ASSERT_EQUAL_INT(1, xce_peers_find_identity(&cfg, ""));
|
||||
printf("test_find_identity_empty_name_matches_empty_hostname: PASS\n");
|
||||
}
|
||||
|
||||
/* ── Test group entry point ─────────────────────────────────────── */
|
||||
void test_cluster(void)
|
||||
{
|
||||
|
|
@ -349,4 +443,11 @@ void test_cluster(void)
|
|||
RUN_TEST(test_peers_env_unset_returns_null);
|
||||
RUN_TEST(test_peers_env_empty_returns_null);
|
||||
RUN_TEST(test_peers_env_nonempty_returned_unchanged);
|
||||
RUN_TEST(test_find_identity_named_match);
|
||||
RUN_TEST(test_find_identity_unnamed_matched_by_hostname);
|
||||
RUN_TEST(test_find_identity_named_not_matched_by_hostname);
|
||||
RUN_TEST(test_find_identity_no_match);
|
||||
RUN_TEST(test_find_identity_first_duplicate_wins);
|
||||
RUN_TEST(test_find_identity_null_name);
|
||||
RUN_TEST(test_find_identity_empty_name_matches_empty_hostname);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue