///|
pub(all) struct NativeStubSourceFunctionRule {
file : String
expected_symbols : Array[String]
} derive(Eq, Debug)
///|
pub(all) struct NativeStubSourceFunctionFact {
file : String
symbol : String
} derive(Eq, Debug)
///|
pub(all) struct NativeStubSourceFunctionPolicyReport {
rule_count : Int
actual_file_count : Int
missing_file_count : Int
extra_file_count : Int
expected_symbol_count : Int
missing_symbol_count : Int
extra_symbol_count : Int
duplicate_symbol_fact_count : Int
replaces_file_reading : Bool
replaces_function_extraction : Bool
live_io_evidence : Bool
} derive(Eq, Debug)
///|
pub fn NativeStubSourceFunctionPolicyReport::passes(
self : NativeStubSourceFunctionPolicyReport,
) -> Bool {
self.rule_count > 0 &&
self.actual_file_count == self.rule_count &&
self.missing_file_count == 0 &&
self.extra_file_count == 0 &&
self.expected_symbol_count > 0 &&
self.missing_symbol_count == 0 &&
self.extra_symbol_count == 0 &&
self.duplicate_symbol_fact_count == 0 &&
!self.replaces_file_reading &&
!self.replaces_function_extraction &&
!self.live_io_evidence
}
///|
pub fn native_stub_source_function_rules() -> Array[
NativeStubSourceFunctionRule,
] {
let rules : Array[NativeStubSourceFunctionRule] = []
rules.push(source_function_rule("stub_common.h", common_helper_symbols()))
rules.push(
source_function_rule("stub_common_status.c", ["lockwire_native_set_error"]),
)
rules.push(
source_function_rule("stub_common_handle.c", [
"lockwire_native_handle_alloc", "lockwire_native_handle_is_valid",
]),
)
rules.push(
source_function_rule("stub_common_bytes.c", [
"lockwire_native_u16_to_network", "lockwire_native_u16_from_network",
]),
)
rules.push(source_function_rule("stub_pcap.h", pcap_helper_symbols()))
rules.push(source_function_rule("stub_pcap_common.c", pcap_helper_symbols()))
rules.push(
source_function_rule("stub_frame_pool.h", frame_pool_helper_symbols()),
)
rules.push(
source_function_rule(
"stub_frame_pool_common.c",
frame_pool_helper_symbols(),
),
)
rules.push(
source_function_rule("stub_npcap_windows.h", npcap_header_symbols()),
)
rules.push(
source_function_rule(
"stub_npcap_windows_common.c",
npcap_common_helper_symbols(),
),
)
rules.push(
source_function_rule("stub_raw_socket_linux.h", raw_socket_helper_symbols()),
)
rules.push(
source_function_rule(
"stub_raw_socket_linux_common.c",
raw_socket_helper_symbols(),
),
)
rules.push(
source_function_rule("stub_udp_windows.h", udp_windows_helper_symbols()),
)
rules.push(
source_function_rule(
"stub_udp_windows_common.c",
udp_windows_helper_symbols(),
),
)
rules.push(
source_function_rule("stub_udp_posix.h", udp_posix_helper_symbols()),
)
rules.push(
source_function_rule("stub_udp_posix_common.c", udp_posix_helper_symbols()),
)
rules.push(
source_function_rule("stub_clock_millis_windows.c", [
"lockwire_native_monotonic_millis",
]),
)
rules.push(
source_function_rule("stub_clock_millis_posix.c", [
"lockwire_native_monotonic_millis",
]),
)
rules.push(
source_function_rule("stub_clock_millis_unsupported.c", [
"lockwire_native_monotonic_millis",
]),
)
rules.push(
source_function_rule("stub_sleep_windows.c", [
"lockwire_native_sleep_until_micros",
]),
)
rules.push(
source_function_rule("stub_sleep_posix.c", [
"lockwire_native_sleep_until_micros",
]),
)
rules.push(
source_function_rule("stub_sleep_unsupported.c", [
"lockwire_native_sleep_until_micros",
]),
)
rules.push(
source_function_rule("stub_rt_affinity_windows.c", [
"lockwire_native_win_rt_set_affinity", "lockwire_native_win_rt_supported",
]),
)
rules.push(
source_function_rule("stub_rt_affinity_unsupported.c", [
"lockwire_native_win_rt_set_affinity", "lockwire_native_win_rt_supported",
]),
)
rules.push(
source_function_rule("stub_npcap_windows_local_mac.c", [
"lockwire_native_npcap_local_mac",
]),
)
rules.push(
source_function_rule("stub_npcap_windows_nonblock.c", [
"lockwire_native_npcap_set_nonblock",
]),
)
rules.push(
source_function_rule("stub_npcap_unsupported_live_ext.c", [
"lockwire_native_npcap_local_mac", "lockwire_native_npcap_last_capture_micros",
"lockwire_native_npcap_set_nonblock",
]),
)
rules.push(
source_function_rule("stub_raw_socket_linux_local_mac.c", [
"lockwire_native_raw_socket_local_mac",
]),
)
rules.push(
source_function_rule("stub_raw_socket_linux_nonblock.c", [
"lockwire_native_raw_socket_set_nonblock",
]),
)
rules.push(
source_function_rule("stub_raw_socket_unsupported_live_ext.c", [
"lockwire_native_raw_socket_local_mac", "lockwire_native_raw_socket_last_capture_micros",
"lockwire_native_raw_socket_set_nonblock",
]),
)
rules
}
///|
pub fn native_stub_expected_source_function_facts() -> Array[
NativeStubSourceFunctionFact,
] {
let facts : Array[NativeStubSourceFunctionFact] = []
for rule in native_stub_source_function_rules() {
for symbol in rule.expected_symbols {
facts.push({ file: rule.file, symbol })
}
}
facts
}
///|
pub fn native_stub_source_function_policy_report(
actual : Array[NativeStubSourceFunctionFact],
) -> NativeStubSourceFunctionPolicyReport {
native_stub_source_function_policy_report_from_rules(
native_stub_source_function_rules(),
actual,
)
}
///|
pub fn native_stub_source_function_policy_report_from_rules(
rules : Array[NativeStubSourceFunctionRule],
actual : Array[NativeStubSourceFunctionFact],
) -> NativeStubSourceFunctionPolicyReport {
{
rule_count: rules.length(),
actual_file_count: count_actual_source_function_files(actual),
missing_file_count: count_missing_source_function_files(rules, actual),
extra_file_count: count_extra_source_function_files(rules, actual),
expected_symbol_count: count_expected_source_function_symbols(rules),
missing_symbol_count: count_missing_source_function_symbols(rules, actual),
extra_symbol_count: count_extra_source_function_symbols(rules, actual),
duplicate_symbol_fact_count: count_duplicate_source_function_facts(actual),
replaces_file_reading: false,
replaces_function_extraction: false,
live_io_evidence: false,
}
}
///|
fn source_function_rule(
file : String,
expected_symbols : Array[String],
) -> NativeStubSourceFunctionRule {
{ file, expected_symbols }
}
///|
fn common_helper_symbols() -> Array[String] {
[
"lockwire_native_set_error", "lockwire_native_handle_alloc", "lockwire_native_handle_is_valid",
"lockwire_native_u16_to_network", "lockwire_native_u16_from_network",
]
}
///|
fn pcap_helper_symbols() -> Array[String] {
[
"lockwire_native_pcap_handle_get", "lockwire_native_pcap_handle_alloc", "lockwire_native_pcap_handle_release",
"lockwire_native_pcap_ensure_parent_dir", "lockwire_native_pcap_timestamp", "lockwire_native_pcap_write_u16_le",
"lockwire_native_pcap_write_u32_le",
]
}
///|
fn frame_pool_helper_symbols() -> Array[String] {
[
"lockwire_native_frame_pool_handle_alloc", "lockwire_native_frame_pool_handle_release",
"lockwire_native_frame_pool_get", "lockwire_native_frame_pool_slot_is_valid",
"lockwire_native_frame_pool_slot_ptr", "lockwire_native_frame_pool_bounds_ok",
]
}
///|
fn npcap_header_symbols() -> Array[String] {
[
"lockwire_native_npcap_ensure", "lockwire_native_npcap_findalldevs", "lockwire_native_npcap_freealldevs",
"lockwire_native_npcap_live_ensure", "lockwire_native_npcap_open_live_handle",
"lockwire_native_npcap_close_handle", "lockwire_native_npcap_sendpacket_handle",
"lockwire_native_npcap_next_ex_handle", "lockwire_native_npcap_geterr_handle",
"lockwire_native_npcap_compile_filter_handle", "lockwire_native_npcap_setfilter_handle",
"lockwire_native_npcap_freecode_handle", "lockwire_native_npcap_live_handle_get",
"lockwire_native_npcap_live_handle_alloc", "lockwire_native_npcap_live_handle_release",
"lockwire_native_npcap_copy_moonbit_bytes_to_c_string",
]
}
///|
fn npcap_common_helper_symbols() -> Array[String] {
[
"lockwire_native_npcap_live_handle_get", "lockwire_native_npcap_live_handle_alloc",
"lockwire_native_npcap_live_handle_release", "lockwire_native_npcap_copy_moonbit_bytes_to_c_string",
]
}
///|
fn raw_socket_helper_symbols() -> Array[String] {
[
"lockwire_native_raw_socket_handle_get", "lockwire_native_raw_socket_handle_alloc",
"lockwire_native_raw_socket_copy_interface_name", "lockwire_native_raw_socket_set_errno_error",
"lockwire_native_raw_socket_handle_release",
]
}
///|
fn udp_windows_helper_symbols() -> Array[String] {
[
"lockwire_native_udp_windows_ensure", "lockwire_native_udp_windows_fill_sockaddr",
"lockwire_native_udp_windows_handle_get", "lockwire_native_udp_windows_handle_alloc",
"lockwire_native_udp_windows_handle_release",
]
}
///|
fn udp_posix_helper_symbols() -> Array[String] {
[
"lockwire_native_udp_posix_fill_sockaddr", "lockwire_native_udp_posix_handle_get",
"lockwire_native_udp_posix_handle_alloc", "lockwire_native_udp_posix_handle_release",
]
}
///|
fn count_actual_source_function_files(
facts : Array[NativeStubSourceFunctionFact],
) -> Int {
let files : Array[String] = []
for fact in facts {
if !source_function_contains_string(files, fact.file) {
files.push(fact.file)
}
}
files.length()
}
///|
fn count_missing_source_function_files(
rules : Array[NativeStubSourceFunctionRule],
actual : Array[NativeStubSourceFunctionFact],
) -> Int {
let mut count = 0
for rule in rules {
if !source_function_contains_file(actual, rule.file) {
count += 1
}
}
count
}
///|
fn count_extra_source_function_files(
rules : Array[NativeStubSourceFunctionRule],
actual : Array[NativeStubSourceFunctionFact],
) -> Int {
let seen : Array[String] = []
let mut count = 0
for fact in actual {
if !source_function_contains_string(seen, fact.file) {
seen.push(fact.file)
if !source_function_contains_rule_file(rules, fact.file) {
count += 1
}
}
}
count
}
///|
fn count_expected_source_function_symbols(
rules : Array[NativeStubSourceFunctionRule],
) -> Int {
let mut count = 0
for rule in rules {
count += rule.expected_symbols.length()
}
count
}
///|
fn count_missing_source_function_symbols(
rules : Array[NativeStubSourceFunctionRule],
actual : Array[NativeStubSourceFunctionFact],
) -> Int {
let mut count = 0
for rule in rules {
for symbol in rule.expected_symbols {
if !source_function_contains_fact(actual, rule.file, symbol) {
count += 1
}
}
}
count
}
///|
fn count_extra_source_function_symbols(
rules : Array[NativeStubSourceFunctionRule],
actual : Array[NativeStubSourceFunctionFact],
) -> Int {
let mut count = 0
for fact in actual {
if !source_function_rule_allows_fact(rules, fact.file, fact.symbol) {
count += 1
}
}
count
}
///|
fn count_duplicate_source_function_facts(
facts : Array[NativeStubSourceFunctionFact],
) -> Int {
let seen : Array[NativeStubSourceFunctionFact] = []
let mut count = 0
for fact in facts {
if source_function_contains_fact(seen, fact.file, fact.symbol) {
count += 1
} else {
seen.push(fact)
}
}
count
}
///|
fn source_function_rule_allows_fact(
rules : Array[NativeStubSourceFunctionRule],
file : String,
symbol : String,
) -> Bool {
for rule in rules {
if rule.file == file &&
source_function_contains_string(rule.expected_symbols, symbol) {
return true
}
}
false
}
///|
fn source_function_contains_rule_file(
rules : Array[NativeStubSourceFunctionRule],
file : String,
) -> Bool {
for rule in rules {
if rule.file == file {
return true
}
}
false
}
///|
fn source_function_contains_file(
facts : Array[NativeStubSourceFunctionFact],
file : String,
) -> Bool {
for fact in facts {
if fact.file == file {
return true
}
}
false
}
///|
fn source_function_contains_fact(
facts : Array[NativeStubSourceFunctionFact],
file : String,
symbol : String,
) -> Bool {
for fact in facts {
if fact.file == file && fact.symbol == symbol {
return true
}
}
false
}
///|
fn source_function_contains_string(
items : Array[String],
item : String,
) -> Bool {
for got in items {
if got == item {
return true
}
}
false
}