| ... | ... | @@ -24,10 +24,12 @@ struct TestCase { |
| 24 | 24 | ZigList<const char *> compile_errors; |
| 25 | 25 | ZigList<const char *> compiler_args; |
| 26 | 26 | ZigList<const char *> program_args; |
| 27 | bool is_parseh; |
| 27 | 28 | }; |
| 28 | 29 | |
| 29 | 30 | static ZigList<TestCase*> test_cases = {0}; |
| 30 | 31 | static const char *tmp_source_path = ".tmp_source.zig"; |
| 32 | static const char *tmp_h_path = ".tmp_header.h"; |
| 31 | 33 | static const char *tmp_exe_path = "./.tmp_exe"; |
| 32 | 34 | static const char *zig_exe = "./zig"; |
| 33 | 35 | |
| ... | ... | @@ -94,6 +96,24 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source |
| 94 | 96 | return test_case; |
| 95 | 97 | } |
| 96 | 98 | |
| 99 | static TestCase *add_parseh_case(const char *case_name, const char *source, const char *output) { |
| 100 | TestCase *test_case = allocate<TestCase>(1); |
| 101 | test_case->case_name = case_name; |
| 102 | test_case->output = output; |
| 103 | test_case->is_parseh = true; |
| 104 | |
| 105 | test_case->source_files.resize(1); |
| 106 | test_case->source_files.at(0).relative_path = tmp_h_path; |
| 107 | test_case->source_files.at(0).source_code = source; |
| 108 | |
| 109 | test_case->compiler_args.append("parseh"); |
| 110 | test_case->compiler_args.append(tmp_h_path); |
| 111 | test_case->compiler_args.append("--c-import-warnings"); |
| 112 | |
| 113 | test_cases.append(test_case); |
| 114 | return test_case; |
| 115 | } |
| 116 | |
| 97 | 117 | static void add_compiling_test_cases(void) { |
| 98 | 118 | add_simple_case("hello world with libc", R"SOURCE( |
| 99 | 119 | #link("c") |
| ... | ... | @@ -1771,6 +1791,39 @@ const x = 2 == 2.0; |
| 1771 | 1791 | |
| 1772 | 1792 | } |
| 1773 | 1793 | |
| 1794 | ////////////////////////////////////////////////////////////////////////////// |
| 1795 | |
| 1796 | static void add_parseh_test_cases(void) { |
| 1797 | add_parseh_case("simple data types", R"SOURCE( |
| 1798 | #include <stdint.h> |
| 1799 | int foo(char a, unsigned char b, signed char c); |
| 1800 | void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); |
| 1801 | void baz(int8_t a, int16_t b, int32_t c, int64_t d); |
| 1802 | )SOURCE", R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; |
| 1803 | pub extern fn bar(a: u8, b: u16, c: u32, d: u64); |
| 1804 | pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT"); |
| 1805 | |
| 1806 | add_parseh_case("noreturn attribute", R"SOURCE( |
| 1807 | void foo(void) __attribute__((noreturn)); |
| 1808 | )SOURCE", R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); |
| 1809 | |
| 1810 | add_parseh_case("enums", R"SOURCE( |
| 1811 | enum Foo { |
| 1812 | FooA, |
| 1813 | FooB, |
| 1814 | Foo1, |
| 1815 | }; |
| 1816 | )SOURCE", R"OUTPUT(export enum enum_Foo { |
| 1817 | A, |
| 1818 | B, |
| 1819 | _1, |
| 1820 | } |
| 1821 | pub const FooA = enum_Foo.A; |
| 1822 | pub const FooB = enum_Foo.B; |
| 1823 | pub const Foo1 = enum_Foo._1; |
| 1824 | pub const Foo = enum_Foo;)OUTPUT"); |
| 1825 | } |
| 1826 | |
| 1774 | 1827 | static void print_compiler_invocation(TestCase *test_case) { |
| 1775 | 1828 | printf("%s", zig_exe); |
| 1776 | 1829 | for (int i = 0; i < test_case->compiler_args.length; i += 1) { |
| ... | ... | @@ -1822,36 +1875,55 @@ static void run_test(TestCase *test_case) { |
| 1822 | 1875 | exit(1); |
| 1823 | 1876 | } |
| 1824 | 1877 | |
| 1825 | | Buf program_stderr = BUF_INIT; |
| 1826 | | Buf program_stdout = BUF_INIT; |
| 1827 | | os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout); |
| 1878 | if (test_case->is_parseh) { |
| 1879 | if (buf_len(&zig_stderr) > 0) { |
| 1880 | printf("\nparseh emitted warnings:\n"); |
| 1881 | print_compiler_invocation(test_case); |
| 1882 | printf("%s\n", buf_ptr(&zig_stderr)); |
| 1883 | exit(1); |
| 1884 | } |
| 1828 | 1885 | |
| 1829 | | if (return_code != 0) { |
| 1830 | | printf("\nProgram exited with return code %d:\n", return_code); |
| 1831 | | print_compiler_invocation(test_case); |
| 1832 | | printf("%s", tmp_exe_path); |
| 1833 | | for (int i = 0; i < test_case->program_args.length; i += 1) { |
| 1834 | | printf(" %s", test_case->program_args.at(i)); |
| 1886 | if (!strstr(buf_ptr(&zig_stdout), test_case->output)) { |
| 1887 | printf("\n"); |
| 1888 | printf("========= Expected this output: =========\n"); |
| 1889 | printf("%s\n", test_case->output); |
| 1890 | printf("================================================\n"); |
| 1891 | print_compiler_invocation(test_case); |
| 1892 | printf("%s\n", buf_ptr(&zig_stdout)); |
| 1893 | exit(1); |
| 1835 | 1894 | } |
| 1836 | | printf("\n"); |
| 1837 | | printf("%s\n", buf_ptr(&program_stderr)); |
| 1838 | | exit(1); |
| 1839 | | } |
| 1895 | } else { |
| 1896 | Buf program_stderr = BUF_INIT; |
| 1897 | Buf program_stdout = BUF_INIT; |
| 1898 | os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout); |
| 1840 | 1899 | |
| 1841 | | if (!buf_eql_str(&program_stdout, test_case->output)) { |
| 1842 | | printf("\n"); |
| 1843 | | print_compiler_invocation(test_case); |
| 1844 | | printf("%s", tmp_exe_path); |
| 1845 | | for (int i = 0; i < test_case->program_args.length; i += 1) { |
| 1846 | | printf(" %s", test_case->program_args.at(i)); |
| 1900 | if (return_code != 0) { |
| 1901 | printf("\nProgram exited with return code %d:\n", return_code); |
| 1902 | print_compiler_invocation(test_case); |
| 1903 | printf("%s", tmp_exe_path); |
| 1904 | for (int i = 0; i < test_case->program_args.length; i += 1) { |
| 1905 | printf(" %s", test_case->program_args.at(i)); |
| 1906 | } |
| 1907 | printf("\n"); |
| 1908 | printf("%s\n", buf_ptr(&program_stderr)); |
| 1909 | exit(1); |
| 1910 | } |
| 1911 | |
| 1912 | if (!buf_eql_str(&program_stdout, test_case->output)) { |
| 1913 | printf("\n"); |
| 1914 | print_compiler_invocation(test_case); |
| 1915 | printf("%s", tmp_exe_path); |
| 1916 | for (int i = 0; i < test_case->program_args.length; i += 1) { |
| 1917 | printf(" %s", test_case->program_args.at(i)); |
| 1918 | } |
| 1919 | printf("\n"); |
| 1920 | printf("==== Test failed. Expected output: ====\n"); |
| 1921 | printf("%s\n", test_case->output); |
| 1922 | printf("========= Actual output: ==============\n"); |
| 1923 | printf("%s\n", buf_ptr(&program_stdout)); |
| 1924 | printf("=======================================\n"); |
| 1925 | exit(1); |
| 1847 | 1926 | } |
| 1848 | | printf("\n"); |
| 1849 | | printf("==== Test failed. Expected output: ====\n"); |
| 1850 | | printf("%s\n", test_case->output); |
| 1851 | | printf("========= Actual output: ==============\n"); |
| 1852 | | printf("%s\n", buf_ptr(&program_stdout)); |
| 1853 | | printf("=======================================\n"); |
| 1854 | | exit(1); |
| 1855 | 1927 | } |
| 1856 | 1928 | |
| 1857 | 1929 | for (int i = 0; i < test_case->source_files.length; i += 1) { |
| ... | ... | @@ -1881,6 +1953,7 @@ static void run_all_tests(bool reverse) { |
| 1881 | 1953 | |
| 1882 | 1954 | static void cleanup(void) { |
| 1883 | 1955 | remove(tmp_source_path); |
| 1956 | remove(tmp_h_path); |
| 1884 | 1957 | remove(tmp_exe_path); |
| 1885 | 1958 | } |
| 1886 | 1959 | |
| ... | ... | @@ -1900,6 +1973,7 @@ int main(int argc, char **argv) { |
| 1900 | 1973 | } |
| 1901 | 1974 | add_compiling_test_cases(); |
| 1902 | 1975 | add_compile_failure_test_cases(); |
| 1976 | add_parseh_test_cases(); |
| 1903 | 1977 | run_all_tests(reverse); |
| 1904 | 1978 | cleanup(); |
| 1905 | 1979 | } |