|
4 | 4 | from eval_protocol.human_id import generate_id, num_combinations |
5 | 5 |
|
6 | 6 |
|
7 | | -def test_generate_id_index_basic_3_words(): |
8 | | - # index 0 maps to the first element of each category (verb, adjective, noun) |
9 | | - assert generate_id(index=0, word_count=3) == "be-other-time" |
10 | | - |
11 | | - # incrementing index advances the least-significant position (noun) |
12 | | - assert generate_id(index=1, word_count=3) == "be-other-year" |
13 | | - |
14 | | - # carry into the adjective when nouns wrap |
15 | | - # index == len(nouns) => adjective advances by 1, noun resets |
16 | | - # nouns length inferred by probing with large indices is brittle; instead, compute via reach |
17 | | - # We know index=0 gives be-other-time, and index that produces adjective=new, noun=time should be reachable. |
18 | | - # Derive by scanning forward until adjective changes to 'new'. This keeps test robust to dictionary size edits. |
19 | | - base = generate_id(index=0, word_count=3) |
20 | | - # Find the first index where adjective becomes 'new' and noun resets to 'time' |
21 | | - target = None |
22 | | - for i in range(1, 2000): |
23 | | - cand = generate_id(index=i, word_count=3) |
24 | | - if cand.startswith("be-new-time"): |
25 | | - target = i |
26 | | - break |
27 | | - assert target is not None, "Expected to find carry into adjective within search bound" |
28 | | - assert generate_id(index=target, word_count=3) == "be-new-time" |
29 | | - |
30 | | - |
31 | | -def test_generate_id_index_word_count_cycle(): |
32 | | - # word_count cycles categories: verb, adj, noun, verb, adj, ... |
33 | | - assert generate_id(index=0, word_count=5) == "be-other-time-be-other" |
34 | | - # increment least-significant position (adj at position 5) |
35 | | - assert generate_id(index=1, word_count=5) == "be-other-time-be-new" |
36 | | - |
37 | | - |
38 | | -def test_generate_id_index_out_of_range_and_negative(): |
39 | | - # Use exported total combinations for clean boundary checks |
40 | | - total = num_combinations(word_count=3) |
| 7 | +def test_generate_id_basic_format(): |
| 8 | + """Test that generate_id produces the expected adjective-noun-NN format""" |
| 9 | + id_str = generate_id(index=0) |
| 10 | + # Should match pattern: adjective-noun-NN where NN is 00-99 |
| 11 | + assert re.match(r"^[a-z]+-[a-z]+-\d{2}$", id_str) |
| 12 | + |
| 13 | + # Test a few specific indices to ensure deterministic behavior |
| 14 | + assert generate_id(index=0) == "other-time-00" |
| 15 | + assert generate_id(index=1) == "other-time-01" |
| 16 | + assert generate_id(index=99) == "other-time-99" |
| 17 | + assert generate_id(index=100) == "other-year-00" |
| 18 | + |
| 19 | + |
| 20 | +def test_generate_id_index_mapping(): |
| 21 | + """Test that index mapping works correctly""" |
| 22 | + # Test number cycling (0-99) |
| 23 | + for i in range(100): |
| 24 | + id_str = generate_id(index=i) |
| 25 | + expected_num = f"{i:02d}" |
| 26 | + assert id_str.endswith(f"-{expected_num}") |
| 27 | + assert id_str.startswith("other-time-") |
| 28 | + |
| 29 | + # Test noun advancement after 100 numbers |
| 30 | + id_100 = generate_id(index=100) |
| 31 | + assert id_100.startswith("other-year-00") |
| 32 | + |
| 33 | + # Test adjective advancement (after all nouns * 100) |
| 34 | + # This will depend on dictionary size, so let's test the pattern |
| 35 | + from eval_protocol.human_id import dictionary |
| 36 | + |
| 37 | + nouns_count = len(dictionary.nouns) |
| 38 | + adjective_boundary = nouns_count * 100 |
| 39 | + |
| 40 | + id_at_boundary = generate_id(index=adjective_boundary) |
| 41 | + # Should have advanced to the next adjective |
| 42 | + assert not id_at_boundary.startswith("other-") |
| 43 | + |
| 44 | + |
| 45 | +def test_generate_id_index_out_of_range(): |
| 46 | + """Test that invalid indices raise appropriate errors""" |
| 47 | + total = num_combinations() |
41 | 48 | assert total > 0 |
42 | | - # Last valid index |
43 | | - generate_id(index=total - 1, word_count=3) |
44 | | - # First invalid index |
| 49 | + |
| 50 | + # Last valid index should work |
| 51 | + generate_id(index=total - 1) |
| 52 | + |
| 53 | + # First invalid index should raise error |
45 | 54 | with pytest.raises(ValueError): |
46 | | - generate_id(index=total, word_count=3) |
| 55 | + generate_id(index=total) |
47 | 56 |
|
| 57 | + # Negative index should raise error |
48 | 58 | with pytest.raises(ValueError): |
49 | | - generate_id(index=-1, word_count=3) |
| 59 | + generate_id(index=-1) |
50 | 60 |
|
51 | 61 |
|
52 | | -def test_generate_id_seed_stability_and_compat(): |
53 | | - # Without index, same seed yields same id |
| 62 | +def test_generate_id_seed_stability(): |
| 63 | + """Test that same seed produces same ID""" |
54 | 64 | a = generate_id(seed=1234) |
55 | 65 | b = generate_id(seed=1234) |
56 | 66 | assert a == b |
57 | 67 |
|
58 | 68 | # Without index, default produces separator '-' and at least 3 components |
59 | 69 | c = generate_id() |
60 | | - assert re.match(r"^[a-z]+(-[a-z]+){2,}$", c) |
| 70 | + |
| 71 | + assert re.match(r"^[a-z]+-[a-z]+-\d{2}$", c) |
61 | 72 |
|
62 | 73 |
|
63 | | -def test_generate_id_index_ignores_seed(): |
64 | | - # With index provided, seed should affect the mapping deterministically |
| 74 | +def test_generate_id_seed_with_index(): |
| 75 | + """Test that seed affects index-based generation deterministically""" |
65 | 76 | x = generate_id(index=42, seed=1) |
66 | 77 | y = generate_id(index=42, seed=999) |
67 | 78 | z = generate_id(index=42, seed=1) |
68 | | - assert x != y |
| 79 | + |
| 80 | + # Same seed should produce same result |
69 | 81 | assert x == z |
| 82 | + # Different seeds should produce different results |
| 83 | + assert x != y |
| 84 | + |
| 85 | + # All should follow the correct format |
| 86 | + assert re.match(r"^[a-z]+-[a-z]+-\d{2}$", x) |
| 87 | + assert re.match(r"^[a-z]+-[a-z]+-\d{2}$", y) |
| 88 | + |
| 89 | + |
| 90 | +def test_generate_id_random_format(): |
| 91 | + """Test that random generation (no index) produces correct format""" |
| 92 | + for _ in range(10): |
| 93 | + id_str = generate_id() |
| 94 | + assert re.match(r"^[a-z]+-[a-z]+-\d{2}$", id_str) |
0 commit comments