| ... | @@ -24,10 +24,12 @@ struct TestCase { | ... | @@ -24,10 +24,12 @@ struct TestCase { |
| 24 | ZigList<const char *> compile_errors; | 24 | ZigList<const char *> compile_errors; |
| 25 | ZigList<const char *> compiler_args; | 25 | ZigList<const char *> compiler_args; |
| 26 | ZigList<const char *> program_args; | 26 | ZigList<const char *> program_args; |
| | 27 | bool is_parseh; |
| 27 | }; | 28 | }; |
| 28 | | 29 | |
| 29 | static ZigList<TestCase*> test_cases = {0}; | 30 | static ZigList<TestCase*> test_cases = {0}; |
| 30 | static const char *tmp_source_path = ".tmp_source.zig"; | 31 | static const char *tmp_source_path = ".tmp_source.zig"; |
| | 32 | static const char *tmp_h_path = ".tmp_header.h"; |
| 31 | static const char *tmp_exe_path = "./.tmp_exe"; | 33 | static const char *tmp_exe_path = "./.tmp_exe"; |
| 32 | static const char *zig_exe = "./zig"; | 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,6 +96,24 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source |
| 94 | return test_case; | 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 | static void add_compiling_test_cases(void) { | 117 | static void add_compiling_test_cases(void) { |
| 98 | add_simple_case("hello world with libc", R"SOURCE( | 118 | add_simple_case("hello world with libc", R"SOURCE( |
| 99 | #link("c") | 119 | #link("c") |
| ... | @@ -1771,6 +1791,39 @@ const x = 2 == 2.0; | ... | @@ -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 | static void print_compiler_invocation(TestCase *test_case) { | 1827 | static void print_compiler_invocation(TestCase *test_case) { |
| 1775 | printf("%s", zig_exe); | 1828 | printf("%s", zig_exe); |
| 1776 | for (int i = 0; i < test_case->compiler_args.length; i += 1) { | 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,36 +1875,55 @@ static void run_test(TestCase *test_case) { |
| 1822 | exit(1); | 1875 | exit(1); |
| 1823 | } | 1876 | } |
| 1824 | | 1877 | |
| 1825 | Buf program_stderr = BUF_INIT; | 1878 | if (test_case->is_parseh) { |
| 1826 | Buf program_stdout = BUF_INIT; | 1879 | if (buf_len(&zig_stderr) > 0) { |
| 1827 | os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout); | 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) { | 1886 | if (!strstr(buf_ptr(&zig_stdout), test_case->output)) { |
| 1830 | printf("\nProgram exited with return code %d:\n", return_code); | 1887 | printf("\n"); |
| 1831 | print_compiler_invocation(test_case); | 1888 | printf("========= Expected this output: =========\n"); |
| 1832 | printf("%s", tmp_exe_path); | 1889 | printf("%s\n", test_case->output); |
| 1833 | for (int i = 0; i < test_case->program_args.length; i += 1) { | 1890 | printf("================================================\n"); |
| 1834 | printf(" %s", test_case->program_args.at(i)); | 1891 | print_compiler_invocation(test_case); |
| | 1892 | printf("%s\n", buf_ptr(&zig_stdout)); |
| | 1893 | exit(1); |
| 1835 | } | 1894 | } |
| 1836 | printf("\n"); | 1895 | } else { |
| 1837 | printf("%s\n", buf_ptr(&program_stderr)); | 1896 | Buf program_stderr = BUF_INIT; |
| 1838 | exit(1); | 1897 | Buf program_stdout = BUF_INIT; |
| 1839 | } | 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)) { | 1900 | if (return_code != 0) { |
| 1842 | printf("\n"); | 1901 | printf("\nProgram exited with return code %d:\n", return_code); |
| 1843 | print_compiler_invocation(test_case); | 1902 | print_compiler_invocation(test_case); |
| 1844 | printf("%s", tmp_exe_path); | 1903 | printf("%s", tmp_exe_path); |
| 1845 | for (int i = 0; i < test_case->program_args.length; i += 1) { | 1904 | for (int i = 0; i < test_case->program_args.length; i += 1) { |
| 1846 | printf(" %s", test_case->program_args.at(i)); | 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 | for (int i = 0; i < test_case->source_files.length; i += 1) { | 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,6 +1953,7 @@ static void run_all_tests(bool reverse) { |
| 1881 | | 1953 | |
| 1882 | static void cleanup(void) { | 1954 | static void cleanup(void) { |
| 1883 | remove(tmp_source_path); | 1955 | remove(tmp_source_path); |
| | 1956 | remove(tmp_h_path); |
| 1884 | remove(tmp_exe_path); | 1957 | remove(tmp_exe_path); |
| 1885 | } | 1958 | } |
| 1886 | | 1959 | |
| ... | @@ -1900,6 +1973,7 @@ int main(int argc, char **argv) { | ... | @@ -1900,6 +1973,7 @@ int main(int argc, char **argv) { |
| 1900 | } | 1973 | } |
| 1901 | add_compiling_test_cases(); | 1974 | add_compiling_test_cases(); |
| 1902 | add_compile_failure_test_cases(); | 1975 | add_compile_failure_test_cases(); |
| | 1976 | add_parseh_test_cases(); |
| 1903 | run_all_tests(reverse); | 1977 | run_all_tests(reverse); |
| 1904 | cleanup(); | 1978 | cleanup(); |
| 1905 | } | 1979 | } |