nx_scene_index_test.nx source
↩ module page · 116 lines · 4352 B
1// nx_scene_index_test.nx -- end-to-end smoke for the full ingestion stack.
2//
3// Verifies the FULL Tier 0 -> Tier 4 chain end-to-end:
4// 1. ingest text (nx_text_ingest)
5// 2. extract terms (nx_term_extract -> nx_term_registry)
6// 3. co-occurrence (nx_term_cooccur)
7// 4. anchor discovery (nx_arc_anchor)
8// 5. scene-candidate build (nx_scene_index)
9//
10// Then queries the index for an OUTFIT_LOCATION candidate and
11// verifies the companion can recover the source byte span.
12//
13// Exit code:
14// 0 all assertions pass
15// N assertion N failed
16
17import "syscalls.nx"
18import "nx_media_pool.nx"
19import "nx_storybeat.nx"
20import "nx_storydb.nx"
21import "nx_text_ingest.nx"
22import "nx_term_registry.nx"
23import "nx_term_extract.nx"
24import "nx_term_cooccur.nx"
25import "nx_arc_anchor.nx"
26import "nx_scene_index.nx"
27
28func main() -> i64 {
29
30 let buf: *u8 = sys_mmap(2048)
31 var k: i64 = 0
32 while k < 2048 { buf[k] = 0; k = k + 1 }
33 let story: *u8 = "Sarah walked into the kitchen wearing an apron.\n\nLater she stood in the kitchen wearing an apron.\n\nShe slipped into the bedroom wearing a robe.\n\nShe was in the bedroom wearing a robe again.\n\nShe stepped into the kitchen wearing an apron.\n"
34 var si: i64 = 0
35 while story[si] != 0 {
36 buf[si] = story[si]
37 si = si + 1
38 }
39 let slen: i64 = si
40
41 let db: *StoryDb = nx_storydb_alloc()
42 let mid: i64 = nx_media_pool_add(db.media_pool, NX_MEDIA_TYPE_TEXT,
43 NX_MEDIA_SRC_USER_PASTE,
44 buf, slen,
45 0 as *u8, 0,
46 0 as *u8, 0,
47 1700000000)
48 if mid < 0 { return 10 }
49 if nx_text_ingest(db, mid) != NX_TEXT_INGEST_OK { return 11 }
50
51 let reg: *TermRegistry = nx_term_registry_alloc()
52 if nx_term_extract_all(db, reg) != NX_EXTR_OK { return 12 }
53
54 let co: *Cooccur = nx_cooccur_alloc()
55 let n_pairs: i64 = nx_cooccur_observe_db(co, db)
56 if n_pairs < 1 { return 13 }
57
58 // Anchor discovery.
59 let scratch_buf: *u8 = sys_mmap(32 * NX_COOCCUR_PAIR_BYTES)
60 let scratch: *CooccurPair = scratch_buf as *CooccurPair
61 let anchor_buf: *u8 = sys_mmap(16 * NX_ARC_ANCHOR_BYTES)
62 let anchors: *ArcAnchor = anchor_buf as *ArcAnchor
63 let n_anch: i64 = nx_arc_anchor_discover(co, reg, scratch, 32,
64 anchors, 16)
65 if n_anch < 1 { return 14 }
66
67 // Scene-index build.
68 let idx: *SceneIndex = nx_scene_index_alloc()
69 let n_built: i64 = nx_scene_index_build(idx, db, anchors, n_anch)
70 if n_built < 1 { return 20 }
71 if idx.n_candidates < 1 { return 21 }
72
73 // Query: first OUTFIT_LOCATION candidate.
74 let cid: i64 = nx_scene_index_first_of_kind(idx,
75 NX_ANCHOR_OUTFIT_LOCATION)
76 if cid < 0 { return 22 }
77 let c: *SceneCandidate = nx_scene_candidate_at(idx, cid)
78 if c.anchor_kind != NX_ANCHOR_OUTFIT_LOCATION { return 23 }
79 if c.best_beat_id < 0 { return 24 }
80 if c.best_beat_id >= db.n_beats { return 25 }
81 if c.source_start < 0 { return 26 }
82 if c.source_end <= c.source_start { return 27 }
83 if c.sighting_count <= 0 { return 28 }
84
85 // Verify source-span query works.
86 var media: i64 = -1
87 var start: i64 = -1
88 var end: i64 = -1
89 if nx_scene_index_source_span(idx, cid, &media, &start, &end) != 0 {
90 return 30
91 }
92 if media != mid { return 31 }
93 if start != c.source_start { return 32 }
94 if end != c.source_end { return 33 }
95
96 // Verify the source-bytes can be looked up via MediaPool.
97 var bytes: *u8 = 0 as *u8
98 var n: i64 = 0
99 if nx_media_pool_get(db.media_pool, media, &bytes, &n) != 0 { return 40 }
100 if n <= 0 { return 41 }
101 if start >= n { return 42 }
102 if end > n { return 43 }
103 // First byte of the span must be non-zero (the source paragraph
104 // is non-empty ASCII).
105 let first_byte: i64 = bytes[start]
106 if first_byte == 0 { return 44 }
107
108 // Verify user-pin promotes stage.
109 let pin_rc: i64 = nx_scene_index_pin(idx, cid)
110 if pin_rc != 0 { return 50 }
111 let c_after: *SceneCandidate = nx_scene_candidate_at(idx, cid)
112 if (c_after.flags & NX_SCENE_FLAG_USER_PINNED) == 0 { return 51 }
113 if c_after.stage != 3 { return 52 }
114
115 return 0
116}