| ... | @@ -96,21 +96,30 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source | ... | @@ -96,21 +96,30 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source |
| 96 | return test_case; | 96 | return test_case; |
| 97 | } | 97 | } |
| 98 | | 98 | |
| 99 | static TestCase *add_parseh_case(const char *case_name, const char *source, const char *output) { | 99 | static TestCase *add_parseh_case(const char *case_name, const char *source, int count, ...) { |
| | 100 | va_list ap; |
| | 101 | va_start(ap, count); |
| | 102 | |
| 100 | TestCase *test_case = allocate<TestCase>(1); | 103 | TestCase *test_case = allocate<TestCase>(1); |
| 101 | test_case->case_name = case_name; | 104 | test_case->case_name = case_name; |
| 102 | test_case->output = output; | | |
| 103 | test_case->is_parseh = true; | 105 | test_case->is_parseh = true; |
| 104 | | 106 | |
| 105 | test_case->source_files.resize(1); | 107 | test_case->source_files.resize(1); |
| 106 | test_case->source_files.at(0).relative_path = tmp_h_path; | 108 | test_case->source_files.at(0).relative_path = tmp_h_path; |
| 107 | test_case->source_files.at(0).source_code = source; | 109 | test_case->source_files.at(0).source_code = source; |
| 108 | | 110 | |
| | 111 | for (int i = 0; i < count; i += 1) { |
| | 112 | const char *arg = va_arg(ap, const char *); |
| | 113 | test_case->compile_errors.append(arg); |
| | 114 | } |
| | 115 | |
| 109 | test_case->compiler_args.append("parseh"); | 116 | test_case->compiler_args.append("parseh"); |
| 110 | test_case->compiler_args.append(tmp_h_path); | 117 | test_case->compiler_args.append(tmp_h_path); |
| 111 | test_case->compiler_args.append("--c-import-warnings"); | 118 | test_case->compiler_args.append("--c-import-warnings"); |
| 112 | | 119 | |
| 113 | test_cases.append(test_case); | 120 | test_cases.append(test_case); |
| | 121 | |
| | 122 | va_end(ap); |
| 114 | return test_case; | 123 | return test_case; |
| 115 | } | 124 | } |
| 116 | | 125 | |
| ... | @@ -1894,13 +1903,13 @@ int foo(char a, unsigned char b, signed char c); | ... | @@ -1894,13 +1903,13 @@ int foo(char a, unsigned char b, signed char c); |
| 1894 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype | 1903 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype |
| 1895 | void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); | 1904 | void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); |
| 1896 | void baz(int8_t a, int16_t b, int32_t c, int64_t d); | 1905 | void baz(int8_t a, int16_t b, int32_t c, int64_t d); |
| 1897 | )SOURCE", R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; | 1906 | )SOURCE", 1, R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; |
| 1898 | pub extern fn bar(a: u8, b: u16, c: u32, d: u64); | 1907 | pub extern fn bar(a: u8, b: u16, c: u32, d: u64); |
| 1899 | pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT"); | 1908 | pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT"); |
| 1900 | | 1909 | |
| 1901 | add_parseh_case("noreturn attribute", R"SOURCE( | 1910 | add_parseh_case("noreturn attribute", R"SOURCE( |
| 1902 | void foo(void) __attribute__((noreturn)); | 1911 | void foo(void) __attribute__((noreturn)); |
| 1903 | )SOURCE", R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); | 1912 | )SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); |
| 1904 | | 1913 | |
| 1905 | add_parseh_case("enums", R"SOURCE( | 1914 | add_parseh_case("enums", R"SOURCE( |
| 1906 | enum Foo { | 1915 | enum Foo { |
| ... | @@ -1908,19 +1917,19 @@ enum Foo { | ... | @@ -1908,19 +1917,19 @@ enum Foo { |
| 1908 | FooB, | 1917 | FooB, |
| 1909 | Foo1, | 1918 | Foo1, |
| 1910 | }; | 1919 | }; |
| 1911 | )SOURCE", R"OUTPUT(export enum enum_Foo { | 1920 | )SOURCE", 1, R"OUTPUT(export enum enum_Foo { |
| 1912 | A, | 1921 | A, |
| 1913 | B, | 1922 | B, |
| 1914 | _1, | 1923 | _1, |
| 1915 | } | 1924 | } |
| 1916 | pub const FooA = enum_Foo.A; | 1925 | pub const FooA = enum_Foo.A; |
| 1917 | pub const FooB = enum_Foo.B; | 1926 | pub const FooB = enum_Foo.B; |
| 1918 | pub const Foo1 = enum_Foo._1; | 1927 | pub const Foo1 = enum_Foo._1;)OUTPUT", |
| 1919 | pub const Foo = enum_Foo;)OUTPUT"); | 1928 | R"OUTPUT(pub const Foo = enum_Foo;)OUTPUT"); |
| 1920 | | 1929 | |
| 1921 | add_parseh_case("restrict -> noalias", R"SOURCE( | 1930 | add_parseh_case("restrict -> noalias", R"SOURCE( |
| 1922 | void foo(void *restrict bar, void *restrict); | 1931 | void foo(void *restrict bar, void *restrict); |
| 1923 | )SOURCE", R"OUTPUT(pub const c_void = u8; | 1932 | )SOURCE", 1, R"OUTPUT(pub const c_void = u8; |
| 1924 | pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT"); | 1933 | pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT"); |
| 1925 | | 1934 | |
| 1926 | add_parseh_case("simple struct", R"SOURCE( | 1935 | add_parseh_case("simple struct", R"SOURCE( |
| ... | @@ -1928,11 +1937,11 @@ struct Foo { | ... | @@ -1928,11 +1937,11 @@ struct Foo { |
| 1928 | int x; | 1937 | int x; |
| 1929 | char *y; | 1938 | char *y; |
| 1930 | }; | 1939 | }; |
| 1931 | )SOURCE", R"OUTPUT(export struct struct_Foo { | 1940 | )SOURCE", 2, |
| | 1941 | R"OUTPUT(export struct struct_Foo { |
| 1932 | x: c_int, | 1942 | x: c_int, |
| 1933 | y: ?&u8, | 1943 | y: ?&u8, |
| 1934 | } | 1944 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1935 | pub const Foo = struct_Foo;)OUTPUT"); | | |
| 1936 | | 1945 | |
| 1937 | add_parseh_case("qualified struct and enum", R"SOURCE( | 1946 | add_parseh_case("qualified struct and enum", R"SOURCE( |
| 1938 | struct Foo { | 1947 | struct Foo { |
| ... | @@ -1944,7 +1953,7 @@ enum Bar { | ... | @@ -1944,7 +1953,7 @@ enum Bar { |
| 1944 | BarB, | 1953 | BarB, |
| 1945 | }; | 1954 | }; |
| 1946 | void func(struct Foo *a, enum Bar **b); | 1955 | void func(struct Foo *a, enum Bar **b); |
| 1947 | )SOURCE", R"OUTPUT(export struct struct_Foo { | 1956 | )SOURCE", 2, R"OUTPUT(export struct struct_Foo { |
| 1948 | x: c_int, | 1957 | x: c_int, |
| 1949 | y: c_int, | 1958 | y: c_int, |
| 1950 | } | 1959 | } |
| ... | @@ -1954,36 +1963,45 @@ export enum enum_Bar { | ... | @@ -1954,36 +1963,45 @@ export enum enum_Bar { |
| 1954 | } | 1963 | } |
| 1955 | pub const BarA = enum_Bar.A; | 1964 | pub const BarA = enum_Bar.A; |
| 1956 | pub const BarB = enum_Bar.B; | 1965 | pub const BarB = enum_Bar.B; |
| 1957 | pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar); | 1966 | pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);)OUTPUT", |
| 1958 | pub const Foo = struct_Foo; | 1967 | R"OUTPUT(pub const Foo = struct_Foo; |
| 1959 | pub const Bar = enum_Bar;)OUTPUT"); | 1968 | pub const Bar = enum_Bar;)OUTPUT"); |
| 1960 | | 1969 | |
| 1961 | add_parseh_case("constant size array", R"SOURCE( | 1970 | add_parseh_case("constant size array", R"SOURCE( |
| 1962 | void func(int array[20]); | 1971 | void func(int array[20]); |
| 1963 | )SOURCE", R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT"); | 1972 | )SOURCE", 1, R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT"); |
| 1964 | | 1973 | |
| 1965 | | 1974 | |
| 1966 | add_parseh_case("self referential struct with function pointer", R"SOURCE( | 1975 | add_parseh_case("self referential struct with function pointer", R"SOURCE( |
| 1967 | struct Foo { | 1976 | struct Foo { |
| 1968 | void (*derp)(struct Foo *foo); | 1977 | void (*derp)(struct Foo *foo); |
| 1969 | }; | 1978 | }; |
| 1970 | )SOURCE", R"OUTPUT(export struct struct_Foo { | 1979 | )SOURCE", 2, R"OUTPUT(export struct struct_Foo { |
| 1971 | derp: ?extern fn (?&struct_Foo), | 1980 | derp: ?extern fn (?&struct_Foo), |
| 1972 | } | 1981 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1973 | pub const Foo = struct_Foo;)OUTPUT"); | | |
| 1974 | | 1982 | |
| 1975 | | 1983 | |
| 1976 | add_parseh_case("struct prototype used in func", R"SOURCE( | 1984 | add_parseh_case("struct prototype used in func", R"SOURCE( |
| 1977 | struct Foo; | 1985 | struct Foo; |
| 1978 | struct Foo *some_func(struct Foo *foo, int x); | 1986 | struct Foo *some_func(struct Foo *foo, int x); |
| 1979 | )SOURCE", R"OUTPUT(pub const struct_Foo = u8; | 1987 | )SOURCE", 2, R"OUTPUT(pub const struct_Foo = u8; |
| 1980 | pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo; | 1988 | pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1981 | pub const Foo = struct_Foo;)OUTPUT"); | 1989 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1982 | | 1990 | |
| 1983 | | 1991 | |
| 1984 | add_parseh_case("#define a char literal", R"SOURCE( | 1992 | add_parseh_case("#define a char literal", R"SOURCE( |
| 1985 | #define A_CHAR 'a' | 1993 | #define A_CHAR 'a' |
| 1986 | )SOURCE", R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); | 1994 | )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); |
| | 1995 | |
| | 1996 | |
| | 1997 | add_parseh_case("#define an unsigned integer literal", R"SOURCE( |
| | 1998 | #define CHANNEL_COUNT 24 |
| | 1999 | )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT"); |
| | 2000 | |
| | 2001 | add_parseh_case("overide previous #define", R"SOURCE( |
| | 2002 | #define A_CHAR 'a' |
| | 2003 | #define A_CHAR 'b' |
| | 2004 | )SOURCE", 1, "pub const A_CHAR = 'b';"); |
| 1987 | } | 2005 | } |
| 1988 | | 2006 | |
| 1989 | static void print_compiler_invocation(TestCase *test_case) { | 2007 | static void print_compiler_invocation(TestCase *test_case) { |
| ... | @@ -2007,7 +2025,7 @@ static void run_test(TestCase *test_case) { | ... | @@ -2007,7 +2025,7 @@ static void run_test(TestCase *test_case) { |
| 2007 | int return_code; | 2025 | int return_code; |
| 2008 | os_exec_process(zig_exe, test_case->compiler_args, &return_code, &zig_stderr, &zig_stdout); | 2026 | os_exec_process(zig_exe, test_case->compiler_args, &return_code, &zig_stderr, &zig_stdout); |
| 2009 | | 2027 | |
| 2010 | if (test_case->compile_errors.length) { | 2028 | if (!test_case->is_parseh && test_case->compile_errors.length) { |
| 2011 | if (return_code) { | 2029 | if (return_code) { |
| 2012 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { | 2030 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { |
| 2013 | const char *err_text = test_case->compile_errors.at(i); | 2031 | const char *err_text = test_case->compile_errors.at(i); |
| ... | @@ -2045,14 +2063,18 @@ static void run_test(TestCase *test_case) { | ... | @@ -2045,14 +2063,18 @@ static void run_test(TestCase *test_case) { |
| 2045 | exit(1); | 2063 | exit(1); |
| 2046 | } | 2064 | } |
| 2047 | | 2065 | |
| 2048 | if (!strstr(buf_ptr(&zig_stdout), test_case->output)) { | 2066 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { |
| 2049 | printf("\n"); | 2067 | const char *output = test_case->compile_errors.at(i); |
| 2050 | printf("========= Expected this output: =========\n"); | 2068 | |
| 2051 | printf("%s\n", test_case->output); | 2069 | if (!strstr(buf_ptr(&zig_stdout), output)) { |
| 2052 | printf("================================================\n"); | 2070 | printf("\n"); |
| 2053 | print_compiler_invocation(test_case); | 2071 | printf("========= Expected this output: =========\n"); |
| 2054 | printf("%s\n", buf_ptr(&zig_stdout)); | 2072 | printf("%s\n", output); |
| 2055 | exit(1); | 2073 | printf("================================================\n"); |
| | 2074 | print_compiler_invocation(test_case); |
| | 2075 | printf("%s\n", buf_ptr(&zig_stdout)); |
| | 2076 | exit(1); |
| | 2077 | } |
| 2056 | } | 2078 | } |
| 2057 | } else { | 2079 | } else { |
| 2058 | Buf program_stderr = BUF_INIT; | 2080 | Buf program_stderr = BUF_INIT; |