diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000..fca150c --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,57 @@ +name: Elixir CI - Linux + +on: push + +jobs: + ubuntu: + runs-on: ubuntu-24.04 + name: Linux OTP ${{matrix.pair.otp-version}} / Elixir ${{matrix.pair.elixir-version}} + strategy: + matrix: + pair: + - otp-version: '27.3' + elixir-version: '1.18.3' + - otp-version: '27.3' + elixir-version: '1.17.3' + - otp-version: '26.2' + elixir-version: '1.16.3' + - otp-version: '25.3' + elixir-version: '1.15.8' + - otp-version: '24.3' + elixir-version: '1.14.5' + steps: + - uses: actions/checkout@v4 + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{matrix.pair.otp-version}} + elixir-version: ${{matrix.pair.elixir-version}} + + - uses: actions/cache@v3 + id: deps-cache + with: + path: deps + key: ${{ runner.os }}-mix-${{ matrix.pair.otp-version }}-${{ matrix.pair.elixir-version }}-${{ hashFiles('/mix.lock') }}-${{ hashfiles('installer/**/*') }} + + - name: Install dependencies + run: mix deps.get + + - uses: actions/cache@v3 + id: build-cache + with: + path: _build + key: ${{ runner.os }}-build-${{ matrix.pair.otp-version }}-${{ matrix.elixir-version }}-${{ hashFiles('/mix.lock') }} + + - name: Compile base + run: mix compile + + - uses: actions/cache@v3 + id: zig-cache + with: + path: test/_support/zig-0.14.0 + key: ${{ runner.os }}-zig-${{ steps.zig-version.outputs.stdout }} + + - name: Run Tests + env: + RUNNING_CI: "TRUE" + ZIGLER_TEST_BLAS: "TRUE" + run: mix test --exclude no_ci diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000..761365d --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,40 @@ +name: Elixir CI - Windows + +on: push + +jobs: + test: + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Elixir + uses: erlef/setup-beam@v1 + with: + elixir-version: '1.18.3' # adjust as needed + otp-version: '27.3' # adjust as needed + + - uses: actions/cache@v3 + id: deps-cache + with: + path: deps + key: ${{ runner.os }}-mix-${{ hashFiles('/mix.lock') }}-${{ hashfiles('/installer/**/*') }} + + - name: Install dependencies + run: mix deps.get + + - uses: actions/cache@v3 + id: build-cache + with: + path: _build + key: ${{ runner.os }}-build-${{ hashFiles('/mix.lock') }} + + - name: Compile base + run: mix compile + + - name: Run Tests + env: + RUNNING_CI: "TRUE" + run: mix test \ No newline at end of file diff --git a/lib/zig.parser.ex b/lib/zig.parser.ex index e0ad068..cd8c8b1 100644 --- a/lib/zig.parser.ex +++ b/lib/zig.parser.ex @@ -255,7 +255,10 @@ defmodule Zig.Parser do end def parse(string) do - case parser(string) do + string + |> String.replace("\r\n", "\n") + |> parser + |> case do {:ok, _, "", parser, _, _} -> %{ parser diff --git a/test/_support/zig_tree.ex b/test/_support/zig_tree.ex index f7c0573..3870b51 100644 --- a/test/_support/zig_tree.ex +++ b/test/_support/zig_tree.ex @@ -16,13 +16,42 @@ defmodule ZigParserTest.ZigTree do end end + @otp_version :otp_release + |> :erlang.system_info() + |> List.to_integer() + + if @otp_version >= 25 do + defp ssl_opts do + [ + verify: :verify_peer, + cacerts: :public_key.cacerts_get() + ] + end + else + defp ssl_opts do + # unfortunately in otp 24 there is not a clean way of obtaining cacerts + [] + end + end + defp download_zig_zipfile do {:ok, _} = Application.ensure_all_started(:ssl) {:ok, _} = Application.ensure_all_started(:inets) headers = [] - request = {~C'https://ziglang.org/builds/zig-0.14.0.tar.xz', headers} - http_options = [timeout: 600_000] + request = {~C'https://ziglang.org/download/0.14.0/zig-0.14.0.tar.xz', headers} + + http_options = [ + timeout: 600_000, + ssl: + [ + depth: 100, + customize_hostname_check: [ + match_fun: :public_key.pkix_verify_hostname_match_fun(:https) + ] + ] ++ ssl_opts() + ] + options = [body_format: :binary] case :httpc.request(:get, request, http_options, options) do diff --git a/test/everything_test.exs b/test/everything_test.exs index 24370b3..cae339e 100644 --- a/test/everything_test.exs +++ b/test/everything_test.exs @@ -1,63 +1,66 @@ -defmodule ZigParserTest.EverythingHelper do - @rejected MapSet.new(~w[ +if match?({:unix, _}, :os.type()) do + defmodule ZigParserTest.EverythingHelper do + @rejected MapSet.new(~w[ # PARSE TOO SLOW: test/_support/zig-0.14.0/src/arch/x86_64/CodeGen.zig + test/_support/zig-0.14.0/lib/compiler_rt/udivmodti4_test.zig ]) - def dir_walk("test/_support/zig-0.14.0/test/cases/compile_errors" <> _), do: [] + def dir_walk("test/_support/zig-0.14.0/test/cases/compile_errors" <> _), do: [] - def dir_walk(dir) do - {dirs, files} = - dir - |> File.ls!() - |> Enum.map(&Path.join(dir, &1)) - |> Enum.split_with(&File.dir?/1) + def dir_walk(dir) do + {dirs, files} = + dir + |> File.ls!() + |> Enum.map(&Path.join(dir, &1)) + |> Enum.split_with(&File.dir?/1) - zig_files = - files - |> Enum.filter(&(Path.extname(&1) == ".zig")) - |> Enum.reject(&(&1 in @rejected)) + zig_files = + files + |> Enum.filter(&(Path.extname(&1) == ".zig")) + |> Enum.reject(&(&1 in @rejected)) - [zig_files | Enum.flat_map(dirs, &dir_walk(&1))] + [zig_files | Enum.flat_map(dirs, &dir_walk(&1))] + end end -end -alias ZigParserTest.EverythingHelper - -parent_dir = "test/_support/zig-0.14.0" -subdirs = ~W[lib src test] - -subdirs -|> Stream.map(&Path.join(parent_dir, &1)) -|> Stream.flat_map(&EverythingHelper.dir_walk/1) -|> Stream.reject(&(&1 == [])) -|> Enum.each(fn [first | _] = files -> - dir = Path.dirname(first) - - mod = - dir - |> String.replace_leading(parent_dir <> "/", "") - |> Macro.camelize() - |> String.replace_prefix("", "Elixir.") - |> String.to_atom() - - code = - quote bind_quoted: binding() do - defmodule mod do - use ExUnit.Case, async: true - @moduletag :everything - - describe dir do - for file <- files do - test file do - unquote(file) - |> File.read!() - |> Zig.Parser.parse() + alias ZigParserTest.EverythingHelper + + parent_dir = "test/_support/zig-0.14.0" + subdirs = ~W[lib src test] + + subdirs + |> Stream.map(&Path.join(parent_dir, &1)) + |> Stream.flat_map(&EverythingHelper.dir_walk/1) + |> Stream.reject(&(&1 == [])) + |> Enum.each(fn [first | _] = files -> + dir = Path.dirname(first) + + mod = + dir + |> String.replace_leading(parent_dir <> "/", "") + |> Macro.camelize() + |> String.replace_prefix("", "Elixir.") + |> String.to_atom() + + code = + quote bind_quoted: binding() do + defmodule mod do + use ExUnit.Case, async: true + @moduletag :everything + + describe dir do + for file <- files do + test file do + unquote(file) + |> File.read!() + |> Zig.Parser.parse() + end end end end end - end - Code.eval_quoted(code) -end) + Code.eval_quoted(code) + end) +end diff --git a/test/parser/switch_test.exs b/test/parser/switch_test.exs index 3eccd66..30f20c6 100644 --- a/test/parser/switch_test.exs +++ b/test/parser/switch_test.exs @@ -96,19 +96,21 @@ defmodule Zig.Parser.Test.SwitchTest do end test "labelled continue" do - assert [%{value: %Switch{prongs: [{[integer: 1], {:continue, :s, _}}], label: :s}}] = Parser.parse(""" - const result = s: switch (@as(u32, 1)) { - 1 => continue :s 123, - }; - """).code + assert [%{value: %Switch{prongs: [{[integer: 1], {:continue, :s, _}}], label: :s}}] = + Parser.parse(""" + const result = s: switch (@as(u32, 1)) { + 1 => continue :s 123, + }; + """).code end test "labelled switch that is a loop." do - assert [%{block: %{code: [%Switch{label: :eval}]}}] = Parser.parse(""" - fn doTheTest() !void { - eval: switch (val) {} - } - """).code + assert [%{block: %{code: [%Switch{label: :eval}]}}] = + Parser.parse(""" + fn doTheTest() !void { + eval: switch (val) {} + } + """).code end end end diff --git a/test/test_helper.exs b/test/test_helper.exs index 8e6d1de..da4f5a6 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,3 +1,5 @@ -ZigParserTest.ZigTree.ensure_zig_directory() +if match?({:unix, _}, :os.type()) do + ZigParserTest.ZigTree.ensure_zig_directory() +end ExUnit.start()