nx_layout_from_dom_test.nx source
↩ module page · 141 lines · 6582 B
1// nx_layout_from_dom_test.nx -- end-to-end smoke proving HTML token
2// stream produces a correct LayoutBox tree.
3//
4// Fixture: "<body><h1>Hi</h1><p>Yo</p></body>"
5//
6// Expected token stream from nx_html_next_token:
7// START_TAG body / START_TAG h1 / TEXT "Hi" / END_TAG h1 /
8// START_TAG p / TEXT "Yo" / END_TAG p / END_TAG body / EOF
9//
10// Expected LayoutBox tree (6 boxes total):
11// box 0: synthetic root (BLOCK, source=-1)
12// box 1: body (BLOCK, parent=0)
13// box 2: h1 (BLOCK, parent=1)
14// box 3: text "Hi" (TEXT, parent=2)
15// box 4: p (BLOCK, parent=1)
16// box 5: text "Yo" (TEXT, parent=4)
17
18import "nx_syscalls.nx"
19import "nx_html_tokenizer.nx"
20import "nx_layout_box.nx"
21import "nx_layout_default_display.nx"
22import "nx_layout_from_dom.nx"
23
24func _put_byte(buf: *u8, i: i64, v: i64) -> i64 {
25 buf[i] = v as u8
26 return 0
27}
28
29func main() -> i64 {
30 // Build fixture: "<body><h1>Hi</h1><p>Yo</p></body>" (32 bytes)
31 let src: *u8 = (sys_mmap(64)) as *u8
32 var p: i64 = 0
33 _put_byte(src, p, 60) p = p + 1 // '<'
34 _put_byte(src, p, 98) p = p + 1 // 'b'
35 _put_byte(src, p, 111) p = p + 1 // 'o'
36 _put_byte(src, p, 100) p = p + 1 // 'd'
37 _put_byte(src, p, 121) p = p + 1 // 'y'
38 _put_byte(src, p, 62) p = p + 1 // '>'
39 _put_byte(src, p, 60) p = p + 1 // '<'
40 _put_byte(src, p, 104) p = p + 1 // 'h'
41 _put_byte(src, p, 49) p = p + 1 // '1'
42 _put_byte(src, p, 62) p = p + 1 // '>'
43 _put_byte(src, p, 72) p = p + 1 // 'H'
44 _put_byte(src, p, 105) p = p + 1 // 'i'
45 _put_byte(src, p, 60) p = p + 1 // '<'
46 _put_byte(src, p, 47) p = p + 1 // '/'
47 _put_byte(src, p, 104) p = p + 1 // 'h'
48 _put_byte(src, p, 49) p = p + 1 // '1'
49 _put_byte(src, p, 62) p = p + 1 // '>'
50 _put_byte(src, p, 60) p = p + 1 // '<'
51 _put_byte(src, p, 112) p = p + 1 // 'p'
52 _put_byte(src, p, 62) p = p + 1 // '>'
53 _put_byte(src, p, 89) p = p + 1 // 'Y'
54 _put_byte(src, p, 111) p = p + 1 // 'o'
55 _put_byte(src, p, 60) p = p + 1 // '<'
56 _put_byte(src, p, 47) p = p + 1 // '/'
57 _put_byte(src, p, 112) p = p + 1 // 'p'
58 _put_byte(src, p, 62) p = p + 1 // '>'
59 _put_byte(src, p, 60) p = p + 1 // '<'
60 _put_byte(src, p, 47) p = p + 1 // '/'
61 _put_byte(src, p, 98) p = p + 1 // 'b'
62 _put_byte(src, p, 111) p = p + 1 // 'o'
63 _put_byte(src, p, 100) p = p + 1 // 'd'
64 _put_byte(src, p, 121) p = p + 1 // 'y'
65 _put_byte(src, p, 62) p = p + 1 // '>'
66 let src_len: i64 = p // 33
67
68 // Allocate LayoutTree + parent stack.
69 let max_boxes: i64 = 16
70 let boxes: *LayoutBox = (sys_mmap((max_boxes * NX_LAYOUT_BOX_BYTES) as nx_size)) as *LayoutBox
71 let tree: *LayoutTree = (sys_mmap(NX_LAYOUT_TREE_BYTES as nx_size)) as *LayoutTree
72 nx_layout_tree_init(tree, boxes, max_boxes)
73
74 let stack_cap: i64 = 16
75 let stk_indices: *i64 = (sys_mmap((stack_cap * 8) as nx_size)) as *i64
76 let stk: *LayoutFromDomStack = (sys_mmap(NX_LAYOUT_FROM_DOM_STACK_BYTES as nx_size)) as *LayoutFromDomStack
77 nx_layout_from_dom_stack_init(stk, stk_indices, stack_cap)
78
79 // Run.
80 let root_idx: i64 = nx_layout_from_dom(src, src_len, tree, stk)
81 if root_idx != 0 { return 1 }
82 if tree.count != 6 { return 2 }
83
84 // Root (box 0): BLOCK, parent=-1, source=-1, first_child=1.
85 let root: *LayoutBox = boxes
86 if root.kind != NX_LAYOUT_BOX_BLOCK { return 10 }
87 if root.parent_idx != -1 { return 11 }
88 if root.source_node_idx != -1 { return 12 }
89 if root.first_child_idx != 1 { return 13 }
90
91 // box 1: body, BLOCK, parent=0, first_child=2, next_sibling=-1.
92 let b1: *LayoutBox = (boxes as *u8 + (1 as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox
93 if b1.kind != NX_LAYOUT_BOX_BLOCK { return 20 }
94 if b1.parent_idx != 0 { return 21 }
95 if b1.first_child_idx != 2 { return 22 }
96 if b1.next_sibling_idx != -1 { return 23 }
97
98 // box 2: h1, BLOCK, parent=1, first_child=3, next_sibling=4.
99 let b2: *LayoutBox = (boxes as *u8 + (2 as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox
100 if b2.kind != NX_LAYOUT_BOX_BLOCK { return 30 }
101 if b2.parent_idx != 1 { return 31 }
102 if b2.first_child_idx != 3 { return 32 }
103 if b2.next_sibling_idx != 4 { return 33 }
104
105 // box 3: TEXT "Hi", parent=2, text_len=2, body bytes match "Hi".
106 let b3: *LayoutBox = (boxes as *u8 + (3 as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox
107 if b3.kind != NX_LAYOUT_BOX_TEXT { return 40 }
108 if b3.parent_idx != 2 { return 41 }
109 if b3.text_len != 2 { return 42 }
110 if (src[b3.text_off] as i64) & 255 != 72 { return 43 } // 'H'
111 if (src[b3.text_off + 1] as i64) & 255 != 105 { return 44 } // 'i'
112
113 // box 4: p, BLOCK, parent=1, first_child=5, next_sibling=-1.
114 let b4: *LayoutBox = (boxes as *u8 + (4 as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox
115 if b4.kind != NX_LAYOUT_BOX_BLOCK { return 50 }
116 if b4.parent_idx != 1 { return 51 }
117 if b4.first_child_idx != 5 { return 52 }
118 if b4.next_sibling_idx != -1 { return 53 }
119
120 // box 5: TEXT "Yo", parent=4.
121 let b5: *LayoutBox = (boxes as *u8 + (5 as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox
122 if b5.kind != NX_LAYOUT_BOX_TEXT { return 60 }
123 if b5.parent_idx != 4 { return 61 }
124 if b5.text_len != 2 { return 62 }
125 if (src[b5.text_off] as i64) & 255 != 89 { return 63 } // 'Y'
126 if (src[b5.text_off + 1] as i64) & 255 != 111 { return 64 } // 'o'
127
128 // Stack should be at depth 1 (only root left after walk).
129 if stk.depth != 1 { return 70 }
130 if stk.indices[0] != 0 { return 71 }
131
132 // Child-count checks via the helper from nx_layout_box.
133 if nx_layout_box_child_count(tree, 0) != 1 { return 80 } // root has 1 child (body)
134 if nx_layout_box_child_count(tree, 1) != 2 { return 81 } // body has 2 children (h1, p)
135 if nx_layout_box_child_count(tree, 2) != 1 { return 82 } // h1 has 1 child (text)
136 if nx_layout_box_child_count(tree, 3) != 0 { return 83 } // text leaf
137 if nx_layout_box_child_count(tree, 4) != 1 { return 84 } // p has 1 child (text)
138 if nx_layout_box_child_count(tree, 5) != 0 { return 85 } // text leaf
139
140 return 0
141}