diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml new file mode 100644 index 0000000..1e8b1c4 --- /dev/null +++ b/.github/workflows/ci-macos.yml @@ -0,0 +1,38 @@ +name: CI (Macos) + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + runs-on: macos-latest + env: + MIX_ENV: test + strategy: + fail-fast: false + steps: + - name: Set up Homebrew + id: set-up-homebrew + uses: Homebrew/actions/setup-homebrew@master + + - name: Install Elixir + env: + HOMEBREW_NO_AUTO_UPDATE: 1 + run: brew install elixir + + - uses: actions/checkout@v3 + + - run: mix deps.get + + - run: mix format --check-formatted + + - run: mix deps.unlock --check-unused + + - run: mix deps.compile + + - run: mix compile --warnings-as-errors + + - run: mix test --only os_macos diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-ubuntu.yml similarity index 73% rename from .github/workflows/ci.yml rename to .github/workflows/ci-ubuntu.yml index 9b5a1f4..6bde285 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-ubuntu.yml @@ -1,4 +1,4 @@ -name: CI +name: CI (Ubuntu) on: pull_request: @@ -23,21 +23,15 @@ jobs: otp: 26.1 lint: lint steps: - - uses: actions/checkout@v3 + - name: Install inotify-tools + run: sudo apt-get update && sudo apt-get install -y inotify-tools - uses: erlef/setup-beam@v1 with: otp-version: ${{matrix.pair.otp}} elixir-version: ${{matrix.pair.elixir}} - - uses: actions/cache@v3 - with: - path: | - deps - _build - key: ${{ runner.os }}-mix-${{matrix.pair.elixir}}-${{matrix.pair.otp}}-${{ hashFiles('**/mix.lock') }} - restore-keys: | - ${{ runner.os }}-mix- + - uses: actions/checkout@v3 - run: mix deps.get @@ -52,4 +46,4 @@ jobs: - run: mix compile --warnings-as-errors if: ${{ matrix.lint }} - - run: mix test + - run: mix test --only os_linux diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml new file mode 100644 index 0000000..30df5e0 --- /dev/null +++ b/.github/workflows/ci-windows.yml @@ -0,0 +1,39 @@ +name: CI (Windows) + +on: + pull_request: + push: + branches: + - main + +jobs: + test: + runs-on: windows-latest + env: + MIX_ENV: test + strategy: + fail-fast: false + matrix: + include: + - pair: + elixir: 1.12.3 + otp: 23.3 + - pair: + elixir: 1.15.7 + otp: 26.1 + + steps: + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{matrix.pair.otp}} + elixir-version: ${{matrix.pair.elixir}} + + - uses: actions/checkout@v3 + + - run: mix deps.get + + - run: mix deps.compile + + - run: mix compile + + - run: mix test --only os_windows diff --git a/.gitignore b/.gitignore index e0d1afd..c400512 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,6 @@ file_system-*.tar /tmp # Misc -/priv/mac_listener +/priv/mac_listener* /priv/kqueue mix.lock diff --git a/lib/file_system/worker.ex b/lib/file_system/worker.ex index 1166cc8..be1f9a1 100644 --- a/lib/file_system/worker.ex +++ b/lib/file_system/worker.ex @@ -1,3 +1,5 @@ +require Logger + defmodule FileSystem.Worker do @moduledoc """ FileSystem Worker Process with the backend GenServer, receive events from Port Process @@ -20,7 +22,9 @@ defmodule FileSystem.Worker do {:ok, backend_pid} <- backend.start_link([{:worker_pid, self()} | rest]) do {:ok, %{backend_pid: backend_pid, subscribers: %{}}} else - _ -> :ignore + reason -> + Logger.warning("Not able to start file_system worker, reason: #{inspect(reason)}") + :ignore end end diff --git a/test/backends/fs_inotify_linux_test.exs b/test/backends/fs_inotify_linux_test.exs new file mode 100644 index 0000000..6408132 --- /dev/null +++ b/test/backends/fs_inotify_linux_test.exs @@ -0,0 +1,110 @@ +defmodule FileSystem.Backends.FSInotifyLinuxTest do + use ExUnit.Case, async: true + import FileSystem.Backends.FSInotify + + @moduletag os_inux: true + + describe "options parse test" do + test "supported options" do + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + ~c"-r", + ~c"/tmp" + ]} == + parse_options(dirs: ["/tmp"], recursive: true) + + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + ~c"/tmp" + ]} == + parse_options(dirs: ["/tmp"], recursive: false) + end + + test "ignore unsupported options" do + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + ~c"/tmp" + ]} == + parse_options(dirs: ["/tmp"], recursive: false, unsupported: :options) + + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + ~c"-r", + ~c"/tmp" + ]} == + parse_options(dirs: ["/tmp"], recursive: :unknown_value) + end + end +end diff --git a/test/backends/fs_inotify_test.exs b/test/backends/fs_inotify_test.exs index 87b44f2..f2f6daf 100644 --- a/test/backends/fs_inotify_test.exs +++ b/test/backends/fs_inotify_test.exs @@ -2,113 +2,13 @@ defmodule FileSystem.Backends.FSInotifyTest do use ExUnit.Case, async: true import FileSystem.Backends.FSInotify + @moduletag os_inux: true, os_windows: true + describe "options parse test" do test "without :dirs" do assert {:error, _} = parse_options([]) assert {:error, _} = parse_options(recursive: 1) end - - test "supported options" do - assert {:ok, - [ - ~c"-e", - ~c"modify", - ~c"-e", - ~c"close_write", - ~c"-e", - ~c"moved_to", - ~c"-e", - ~c"moved_from", - ~c"-e", - ~c"create", - ~c"-e", - ~c"delete", - ~c"-e", - ~c"attrib", - ~c"--format", - [37, 119, 1, 37, 101, 1, 37, 102], - ~c"--quiet", - ~c"-m", - ~c"-r", - ~c"/tmp" - ]} == - parse_options(dirs: ["/tmp"], recursive: true) - - assert {:ok, - [ - ~c"-e", - ~c"modify", - ~c"-e", - ~c"close_write", - ~c"-e", - ~c"moved_to", - ~c"-e", - ~c"moved_from", - ~c"-e", - ~c"create", - ~c"-e", - ~c"delete", - ~c"-e", - ~c"attrib", - ~c"--format", - [37, 119, 1, 37, 101, 1, 37, 102], - ~c"--quiet", - ~c"-m", - ~c"/tmp" - ]} == - parse_options(dirs: ["/tmp"], recursive: false) - end - - test "ignore unsupported options" do - assert {:ok, - [ - ~c"-e", - ~c"modify", - ~c"-e", - ~c"close_write", - ~c"-e", - ~c"moved_to", - ~c"-e", - ~c"moved_from", - ~c"-e", - ~c"create", - ~c"-e", - ~c"delete", - ~c"-e", - ~c"attrib", - ~c"--format", - [37, 119, 1, 37, 101, 1, 37, 102], - ~c"--quiet", - ~c"-m", - ~c"/tmp" - ]} == - parse_options(dirs: ["/tmp"], recursive: false, unsupported: :options) - - assert {:ok, - [ - ~c"-e", - ~c"modify", - ~c"-e", - ~c"close_write", - ~c"-e", - ~c"moved_to", - ~c"-e", - ~c"moved_from", - ~c"-e", - ~c"create", - ~c"-e", - ~c"delete", - ~c"-e", - ~c"attrib", - ~c"--format", - [37, 119, 1, 37, 101, 1, 37, 102], - ~c"--quiet", - ~c"-m", - ~c"-r", - ~c"/tmp" - ]} == - parse_options(dirs: ["/tmp"], recursive: :unknown_value) - end end describe "port line parse test" do diff --git a/test/backends/fs_inotify_windows_test.exs b/test/backends/fs_inotify_windows_test.exs new file mode 100644 index 0000000..2eb7735 --- /dev/null +++ b/test/backends/fs_inotify_windows_test.exs @@ -0,0 +1,114 @@ +defmodule FileSystem.Backends.FSInotifyWindowsTest do + use ExUnit.Case, async: true + import FileSystem.Backends.FSInotify + + @moduletag os_windows: true + + describe "options parse test" do + test "supported options" do + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + ~c"-r", + tmp_dir + ]} = parse_options(dirs: ["/tmp"], recursive: true) + + assert tmp_dir |> to_string() |> String.ends_with?("/tmp") + + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + tmp_dir + ]} = parse_options(dirs: ["/tmp"], recursive: false) + + assert tmp_dir |> to_string() |> String.ends_with?("/tmp") + end + + test "ignore unsupported options" do + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + tmp_dir + ]} = parse_options(dirs: ["/tmp"], recursive: false, unsupported: :options) + + assert tmp_dir |> to_string() |> String.ends_with?("/tmp") + + assert {:ok, + [ + ~c"-e", + ~c"modify", + ~c"-e", + ~c"close_write", + ~c"-e", + ~c"moved_to", + ~c"-e", + ~c"moved_from", + ~c"-e", + ~c"create", + ~c"-e", + ~c"delete", + ~c"-e", + ~c"attrib", + ~c"--format", + [37, 119, 1, 37, 101, 1, 37, 102], + ~c"--quiet", + ~c"-m", + ~c"-r", + tmp_dir + ]} = parse_options(dirs: ["/tmp"], recursive: :unknown_value) + + assert tmp_dir |> to_string() |> String.ends_with?("/tmp") + end + end +end diff --git a/test/backends/fs_mac_test.exs b/test/backends/fs_mac_test.exs index 0a64d66..f1fbd0a 100644 --- a/test/backends/fs_mac_test.exs +++ b/test/backends/fs_mac_test.exs @@ -2,6 +2,8 @@ defmodule FileSystem.Backends.FSMacTest do use ExUnit.Case, async: true import FileSystem.Backends.FSMac + @moduletag os_macos: true + describe "options parse test" do test "without :dirs" do assert {:error, _} = parse_options([]) diff --git a/test/backends/fs_poll_test.exs b/test/backends/fs_poll_test.exs index 39c1f23..b38e6bc 100644 --- a/test/backends/fs_poll_test.exs +++ b/test/backends/fs_poll_test.exs @@ -2,6 +2,8 @@ defmodule FileSystem.Backends.FSPollTest do use ExUnit.Case, async: true import FileSystem.Backends.FSPoll + @moduletag os_linux: true, os_macos: true, os_windows: true + @mtime1 {{2017, 11, 13}, {10, 14, 00}} @mtime2 {{2017, 11, 13}, {10, 15, 00}} diff --git a/test/file_system_test.exs b/test/file_system_test.exs index 7b59b6d..d9f134c 100644 --- a/test/file_system_test.exs +++ b/test/file_system_test.exs @@ -1,6 +1,11 @@ defmodule FileSystemTest do use ExUnit.Case, async: true + # TODO: windows-latest runtime by github action won't pass the test below + # will do a manual debug on a physical machine once have a chance + # add @moduletag os_windows: true to make suer the test be run on windows after fix this + @moduletag os_linux: true, os_macos: true + test "file event api" do tmp_dir = System.cmd("mktemp", ["-d"]) |> elem(0) |> String.trim() {:ok, pid} = FileSystem.start_link(dirs: [tmp_dir])