1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
|
"""
Tests for all examples mentioned in the README.
These tests ensure that the documentation examples actually work.
⚠️ IMPORTANT REMINDER FOR AI ASSISTANTS:
When you modify any test in this file, you MUST also check and update the corresponding
examples in /home/philip/kot/netencode/README.md to ensure they match the test requirements.
If a test expects 't5:hello,' (with comma), the README must show 't5:hello,' (with comma).
If a test expects complete netencode format, the README examples must be complete.
DO NOT just fix tests - always verify and update README examples to match!
"""
import pytest
import subprocess
from conftest import run_tool, get_tool_path
import netencode as ne
class TestReadmeExamples:
"""Test all the examples shown in the README."""
def test_binary_data_construction_with_printf(self):
"""Test the exact example from README: Create filename with non-UTF-8 bytes."""
# Create filename with non-UTF-8 bytes using shell
cmd = ['bash', '-c', 'FILENAME=$(printf "file\\xff\\x00name"); LENGTH=$(printf "%s" "$FILENAME" | wc -c); echo $LENGTH']
result = subprocess.run(cmd, capture_output=True, text=True)
# Should get correct length (9 bytes)
length = int(result.stdout.strip())
assert length == 9
# Create netencode binary string
cmd2 = ['bash', '-c', 'FILENAME=$(printf "file\\xff\\x00name"); LENGTH=$(printf "%s" "$FILENAME" | wc -c); printf "b${LENGTH}:${FILENAME},"']
result2 = subprocess.run(cmd2, capture_output=True)
# Should start with correct prefix and have correct total length
assert result2.stdout.startswith(b'b9:')
assert len(result2.stdout) == 13 # b9: + 9 bytes + ,
def test_simple_printf_construction(self):
"""Test the printf construction example from README."""
text = "Hello, World!"
length = len(text.encode('utf-8'))
result_format = f"b{length}:{text},"
# Should create valid netencode binary string
assert result_format == "b13:Hello, World!,"
def test_basic_record_field_extraction(self):
"""Test extracting name field from record."""
record = ne.simple_record(name=ne.text("Alice"), age=ne.integer(30))
result = run_tool('netencode-record-get', 'name', stdin=record)
# Should extract name field
assert result.stdout.strip() == b't5:Alice,'
def test_basic_record_field_extraction_with_plain(self):
"""Test extracting name field and converting to plain text - README example."""
# Test the exact example: echo '{...}' | netencode-record-get name | netencode-plain
record = ne.simple_record(name=ne.text("Alice"), age=ne.integer(30))
field_result = run_tool('netencode-record-get', 'name', stdin=record)
plain_result = run_tool('netencode-plain', stdin=field_result.stdout)
# Should extract name as plain text
assert plain_result.stdout == b'Alice'
def test_configuration_extraction_with_plain(self):
"""Test configuration example from README with netencode-plain."""
# README example: Extract HOST and PORT from config
config = '{55:<4:host|t9:localhost,<4:port|n:8080,<5:debug|<4:true|u,}'
# Extract host and convert to plain
host_field = run_tool('netencode-record-get', 'host', stdin=config)
host_plain = run_tool('netencode-plain', stdin=host_field.stdout)
assert host_plain.stdout == b'localhost'
# Extract port and convert to plain
port_field = run_tool('netencode-record-get', 'port', stdin=config)
port_plain = run_tool('netencode-plain', stdin=port_field.stdout)
assert port_plain.stdout == b'8080'
def test_environment_integration_with_record_splice_env(self):
"""Test the echo example from README."""
record = ne.simple_record(name=ne.text("Alice"), age=ne.integer(30))
# Use shell -c to properly expand variables
result = run_tool('netencode-to-env', 'sh', '-c', 'echo "Hello $name, you are $age years old"',
stdin=record)
# Should expand environment variables from record
assert result.stdout.strip() == b'Hello Alice, you are 30 years old'
def test_env_splice_record_basic_functionality(self):
"""Test that env-to-netencode produces valid netencode."""
# Set some test environment variables
env = {'TEST_VAR1': 'test_value', 'TEST_VAR2': 'another_value'}
# Run env-to-netencode with custom environment
from conftest import get_tool_path
tool_path = get_tool_path('env-to-netencode')
result = subprocess.run(
[tool_path],
capture_output=True, text=True, env={**env}
)
# Should be a valid netencode record (starts with { and length)
assert result.stdout.startswith('{')
assert ':<' in result.stdout # Should contain tagged fields
# Should contain our test variables
assert 'TEST_VAR1' in result.stdout
assert 'test_value' in result.stdout
def test_json_escaping_vs_netencode_simplicity(self):
"""Test that netencode handles quotes without escaping."""
text = 'He said "Hello"'
length = len(text.encode('utf-8'))
result_format = f't{length}:{text},'
# Should contain quotes literally (no escaping)
assert result_format == 't15:He said "Hello",'
def test_netencode_construction_from_shell_primitives(self):
"""Test that we can construct netencode using only printf and wc."""
name = "Alice"
age = "30"
active = "true"
# Construct individual fields (simplified version)
name_field = f'<4:name|t{len(name)}:{name},'
age_field = f'<3:age|n:{age},'
active_field = f'<6:active|<{len(active)}:{active}|u,'
# Calculate total length
content = name_field + age_field + active_field
total_length = len(content)
# Construct record
record = f'{{{total_length}:{content}}}'
# Should be parseable by netencode-record-get
name_result = run_tool('netencode-record-get', 'name', stdin=record)
assert name_result.stdout.strip() == f't{len(name)}:{name},'.encode('utf-8')
age_result = run_tool('netencode-record-get', 'age', stdin=record)
assert age_result.stdout.strip() == f'n:{age},'.encode('utf-8')
def test_pipeline_data_transformation(self):
"""Test complex pipeline similar to README example."""
# Create test records
record1 = '{"name": "Alice", "email": "alice@example.com", "status": "active"}'
record2 = '{"name": "Bob", "email": "bob@example.com", "status": "inactive"}'
# Convert to netencode
ne1 = run_tool('json-to-netencode', stdin=record1).stdout.strip()
ne2 = run_tool('json-to-netencode', stdin=record2).stdout.strip()
input_stream = ne1 + b'\n' + ne2
# Filter active records
filtered = run_tool('netencode-filter', 'status=active', stdin=input_stream)
# Should only contain Alice's record
assert b'Alice' in filtered.stdout
assert b'Bob' not in filtered.stdout
# Extract fields using netencode-record-get
name_result = run_tool('netencode-record-get', 'name', stdin=filtered.stdout.strip())
email_result = run_tool('netencode-record-get', 'email', stdin=filtered.stdout.strip())
# Extract the actual values (remove netencode formatting)
name = name_result.stdout.strip()
email = email_result.stdout.strip()
# Should extract correct values in netencode format
assert b'Alice' in name
assert b'alice@example.com' in email
def test_complete_pipeline_with_plain_output(self):
"""Test the complete pipeline example from README CLI Tools section."""
# Use individual records as input (like streaming from an API) rather than an array
alice_json = '{"name": "Alice", "active": true}'
bob_json = '{"name": "Bob", "active": false}'
# Convert each to netencode
alice_ne = run_tool('json-to-netencode', stdin=alice_json).stdout.strip()
bob_ne = run_tool('json-to-netencode', stdin=bob_json).stdout.strip()
input_stream = alice_ne + b'\n' + bob_ne
# Filter active users
filtered_data = run_tool('netencode-filter', 'active=true', stdin=input_stream)
# Extract name field from filtered result
name_field = run_tool('netencode-record-get', 'name', stdin=filtered_data.stdout.strip())
# Convert to plain text
plain_name = run_tool('netencode-plain', stdin=name_field.stdout)
# Should get Alice as plain text
assert plain_name.stdout == b'Alice'
def test_type_safety_naturals_vs_integers(self):
"""Test that netencode distinguishes number types correctly."""
natural = '{"count": 42}'
integer = '{"temperature": -10}'
natural_ne = run_tool('json-to-netencode', stdin=natural).stdout.strip()
integer_ne = run_tool('json-to-netencode', stdin=integer).stdout.strip()
# Extract the values
count_result = run_tool('netencode-record-get', 'count', stdin=natural_ne).stdout.strip()
temp_result = run_tool('netencode-record-get', 'temperature', stdin=integer_ne).stdout.strip()
# Should be properly typed (JSON-to-netencode uses i: for all numbers)
assert count_result == b'i:42,'
assert temp_result == b'i:-10,'
def test_length_prefixed_streaming_advantage(self):
"""Test that we can skip over data without parsing it."""
record1 = ne.simple_record(name=ne.text("Alice"), age=ne.integer(30))
record2 = ne.simple_record(name=ne.text("Bob"), age=ne.integer(25))
# Should be able to extract fields from each record
first_name = run_tool('netencode-record-get', 'name', stdin=record1).stdout.strip()
second_name = run_tool('netencode-record-get', 'name', stdin=record2).stdout.strip()
assert first_name == b't5:Alice,'
assert second_name == b't3:Bob,'
def test_boolean_representation_as_tagged_units(self):
"""Test boolean conversion to tagged units."""
bool_record = '{"active": true, "disabled": false}'
result = run_tool('json-to-netencode', stdin=bool_record)
# Should convert to tagged units
assert b'<6:active|<4:true|u,' in result.stdout
assert b'<8:disabled|<5:false|u,' in result.stdout
# Should be extractable
active_result = run_tool('netencode-record-get', 'active', stdin=result.stdout.strip())
assert active_result.stdout.strip() == b'<4:true|u,'
def test_github_api_processing_simplified(self):
"""Test a simplified version that matches what our tools can actually do."""
# Create mock GitHub API response for a single repo
mock_repo = '{"name": "Hello-World", "archived": false, "description": "My first repository"}'
# Convert to netencode
netencode_repo = run_tool('json-to-netencode', stdin=mock_repo).stdout.strip()
# Extract repository name
repo_name = run_tool('netencode-record-get', 'name', stdin=netencode_repo).stdout.strip()
assert repo_name == b't11:Hello-World,'
# Check if archived field can be extracted
archived_status = run_tool('netencode-record-get', 'archived', stdin=netencode_repo).stdout.strip()
assert archived_status == b'<5:false|u,'
def test_hello_netencode_json_conversion(self):
"""Test the Hello World JSON to netencode conversion."""
json_data = '{"message": "Hello, World!"}'
result = run_tool('json-to-netencode', stdin=json_data)
assert result.returncode == 0
assert result.stdout.strip() == b'{29:<7:message|t13:Hello, World!,}'
def test_hello_netencode_pretty_print(self):
"""Test pretty printing the complex example from Hello Netencode section."""
json_data = '{"name": "Alice", "age": 30, "active": true}'
# Convert and pretty print
netencode_result = run_tool('json-to-netencode', stdin=json_data)
pretty_result = run_tool('netencode-pretty', stdin=netencode_result.stdout)
assert pretty_result.returncode == 0
assert b'Alice' in pretty_result.stdout
assert b'active' in pretty_result.stdout
assert b'age' in pretty_result.stdout
def test_hello_netencode_full_pipeline(self):
"""Test the complete field extraction pipeline from Hello Netencode section."""
json_data = '{"name": "Alice", "age": 30, "active": true}'
# Full pipeline: JSON -> netencode -> record-get -> plain
netencode_result = run_tool('json-to-netencode', stdin=json_data)
get_result = run_tool('netencode-record-get', 'name', stdin=netencode_result.stdout)
plain_result = run_tool('netencode-plain', stdin=get_result.stdout)
assert plain_result.returncode == 0
assert plain_result.stdout == b'Alice'
def test_basic_user_record_creation(self):
"""Test creating a user record from JSON."""
json_data = '{"name": "Alice", "age": 30, "active": true}'
result = run_tool('json-to-netencode', stdin=json_data)
assert result.returncode == 0
assert result.stdout.strip() == b'{49:<6:active|<4:true|u,<3:age|i:30,<4:name|t5:Alice,}'
def test_basic_field_extraction(self):
"""Test extracting name field from user record."""
json_data = '{"name": "Alice", "age": 30}'
# Convert to netencode and extract name
netencode_result = run_tool('json-to-netencode', stdin=json_data)
get_result = run_tool('netencode-record-get', 'name', stdin=netencode_result.stdout)
plain_result = run_tool('netencode-plain', stdin=get_result.stdout)
assert plain_result.returncode == 0
assert plain_result.stdout == b'Alice'
def test_filter_multiple_records(self):
"""Test filtering multiple user records."""
# Create test data
alice = '{"name": "Alice", "active": true}'
bob = '{"name": "Bob", "active": false}'
# Convert both to netencode
alice_ne = run_tool('json-to-netencode', stdin=alice).stdout
bob_ne = run_tool('json-to-netencode', stdin=bob).stdout
# Combine records
combined = alice_ne + bob_ne
# Filter active users
filter_result = run_tool('netencode-filter', 'active=true', stdin=combined)
assert filter_result.returncode == 0
assert b'Alice' in filter_result.stdout
assert b'Bob' not in filter_result.stdout
def test_python_user_record_creation(self):
"""Test the Python example for creating a user record."""
# This tests that the Python code shown in the README actually works
import netencode as ne
user = ne.record([
("name", ne.text("Alice")),
("age", ne.integer(30)),
("active", ne.boolean(True))
])
assert user == b'{49:<4:name|t5:Alice,<3:age|i:30,<6:active|<4:true|u,}'
def test_python_nested_structure(self):
"""Test the Python example for creating nested structures."""
import netencode as ne
config = ne.record([
("database", ne.record([
("host", ne.text("localhost")),
("port", ne.integer(5432))
])),
("debug", ne.boolean(False))
])
# Verify it creates valid netencode
assert config.startswith(b'{')
assert b'database' in config
assert b'localhost' in config
assert b'5432' in config
assert b'<5:false|u,' in config
|