| 1 | module builder |
| 2 | |
| 3 | import os |
| 4 | import v2.ast |
| 5 | |
| 6 | fn test_parse_fn_signature_and_return_generic_params_with_space() { |
| 7 | info := parse_fn_signature_and_return('pub fn run_at[A, X](mut global_app A, params RunParams) ! {') or { |
| 8 | assert false |
| 9 | return |
| 10 | } |
| 11 | assert info.signature == 'pub fn run_at[A, X](mut global_app A, params RunParams)' |
| 12 | assert info.return_type == '!' |
| 13 | } |
| 14 | |
| 15 | fn test_sanitize_staged_c_source_addresses_channel_semaphore_waits() { |
| 16 | source := [ |
| 17 | 'sync__Semaphore__wait(ch->writesem);', |
| 18 | 'sync__Semaphore__wait(&ch->readsem);', |
| 19 | ].join('\n') |
| 20 | sanitized := sanitize_staged_c_source(source) |
| 21 | assert sanitized.contains('sync__Semaphore__wait(&ch->writesem);') |
| 22 | assert sanitized.contains('sync__Semaphore__wait(&ch->readsem);') |
| 23 | assert !sanitized.contains('sync__Semaphore__wait(ch->writesem);') |
| 24 | assert !sanitized.contains('sync__Semaphore__wait(&&ch->readsem);') |
| 25 | } |
| 26 | |
| 27 | fn test_sanitize_cached_main_c_source_addresses_channel_semaphore_waits() { |
| 28 | source := [ |
| 29 | 'sync__Semaphore__wait(ch->writesem);', |
| 30 | 'sync__Semaphore__wait(&ch->readsem);', |
| 31 | ].join('\n') |
| 32 | sanitized := sanitize_cached_main_c_source(source) |
| 33 | assert sanitized.contains('sync__Semaphore__wait(&ch->writesem);') |
| 34 | assert sanitized.contains('sync__Semaphore__wait(&ch->readsem);') |
| 35 | assert !sanitized.contains('sync__Semaphore__wait(ch->writesem);') |
| 36 | assert !sanitized.contains('sync__Semaphore__wait(&&ch->readsem);') |
| 37 | } |
| 38 | |
| 39 | fn test_sanitize_cached_main_c_source_uses_c_typedef_names_for_sync_fields() { |
| 40 | source := [ |
| 41 | 'struct atomic_uintptr_t write_adr;', |
| 42 | 'struct pthread_rwlockattr_t attr;', |
| 43 | 'struct pthread_condattr_t attr;', |
| 44 | ].join('\n') |
| 45 | sanitized := sanitize_cached_main_c_source(source) |
| 46 | assert sanitized.contains('atomic_uintptr_t write_adr;') |
| 47 | assert sanitized.contains('pthread_rwlockattr_t attr;') |
| 48 | assert sanitized.contains('pthread_condattr_t attr;') |
| 49 | assert !sanitized.contains('struct atomic_uintptr_t write_adr;') |
| 50 | assert !sanitized.contains('struct pthread_rwlockattr_t attr;') |
| 51 | assert !sanitized.contains('struct pthread_condattr_t attr;') |
| 52 | } |
| 53 | |
| 54 | fn test_sanitize_cached_object_c_source_uses_c_typedef_names_for_sync_fields() { |
| 55 | source := [ |
| 56 | 'struct atomic_uintptr_t write_adr;', |
| 57 | 'struct atomic_uintptr_t read_adr;', |
| 58 | ].join('\n') |
| 59 | sanitized := sanitize_cached_object_c_source(source) |
| 60 | assert sanitized.contains('atomic_uintptr_t write_adr;') |
| 61 | assert sanitized.contains('atomic_uintptr_t read_adr;') |
| 62 | assert !sanitized.contains('struct atomic_uintptr_t write_adr;') |
| 63 | assert !sanitized.contains('struct atomic_uintptr_t read_adr;') |
| 64 | } |
| 65 | |
| 66 | fn test_sanitize_cached_source_guards_stdatomic_preamble_for_tcc_compat_header() { |
| 67 | source := [ |
| 68 | '#include <stdint.h>', |
| 69 | '#include <stdatomic.h>', |
| 70 | '#include "/tmp/vroot/thirdparty/stdatomic/nix/atomic.h"', |
| 71 | ].join('\n') |
| 72 | sanitized := sanitize_cached_object_c_source(source) |
| 73 | assert sanitized.contains('#ifndef __TINYC__\n#include <stdatomic.h>\n#endif') |
| 74 | assert sanitized.contains('#define extern static\n#endif\n#include "/tmp/vroot/thirdparty/stdatomic/nix/atomic.h"') |
| 75 | assert sanitized.contains('#undef extern') |
| 76 | assert sanitized.contains('#include "/tmp/vroot/thirdparty/stdatomic/nix/atomic.h"') |
| 77 | } |
| 78 | |
| 79 | fn test_sanitize_cached_source_keeps_stdatomic_preamble_without_compat_header() { |
| 80 | source := [ |
| 81 | '#include <stdint.h>', |
| 82 | '#include <stdatomic.h>', |
| 83 | ].join('\n') |
| 84 | sanitized := sanitize_cached_object_c_source(source) |
| 85 | assert sanitized == source |
| 86 | } |
| 87 | |
| 88 | fn test_join_flag_strings_deduplicates_partial_overlap() { |
| 89 | flags := join_flag_strings('/tmp/sqlite3.c -lm -lpthread', |
| 90 | '/tmp/sqlite3.c -lm -lssl -lcrypto -L/tmp/ssl -lpthread') |
| 91 | assert flags == '/tmp/sqlite3.c -lm -lpthread -lssl -lcrypto -L/tmp/ssl' |
| 92 | } |
| 93 | |
| 94 | fn test_join_flag_strings_keeps_distinct_two_token_flags() { |
| 95 | flags := join_flag_strings('-I /tmp/a -framework Cocoa', |
| 96 | '-I /tmp/a -I /tmp/b -framework Foundation') |
| 97 | assert flags == '-I /tmp/a -framework Cocoa -I /tmp/b -framework Foundation' |
| 98 | } |
| 99 | |
| 100 | fn test_user_entry_stamp_files_expands_directory_to_parsed_files() { |
| 101 | tmp_dir := os.join_path(os.temp_dir(), 'v2_cache_entry_${os.getpid()}') |
| 102 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 103 | defer { |
| 104 | os.rmdir_all(tmp_dir) or {} |
| 105 | } |
| 106 | source_file := os.join_path(tmp_dir, 'main.v') |
| 107 | header_file := os.join_path(tmp_dir, 'main.vh') |
| 108 | mut b := Builder{ |
| 109 | pref: unsafe { nil } |
| 110 | user_files: [tmp_dir] |
| 111 | files: [ |
| 112 | ast.File{ |
| 113 | name: source_file |
| 114 | }, |
| 115 | ast.File{ |
| 116 | name: header_file |
| 117 | }, |
| 118 | ast.File{}, |
| 119 | ] |
| 120 | } |
| 121 | files := b.user_entry_stamp_files() |
| 122 | assert files == [os.norm_path(source_file)] |
| 123 | assert os.norm_path(tmp_dir) !in files |
| 124 | } |
| 125 | |