diff --git a/lib/fledex/component/dot.ex b/lib/fledex/component/dot.ex index b116eec..4db535f 100644 --- a/lib/fledex/component/dot.ex +++ b/lib/fledex/component/dot.ex @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 defmodule Fledex.Component.Dot do @behaviour Fledex.Component.Interface + import Fledex.Utils.Guards @impl true def configure(name, options) when is_atom(name) and is_list(options) do @@ -16,10 +17,7 @@ defmodule Fledex.Component.Dot do triggers when is_map(triggers) and is_map_key(triggers, trigger_name) -> trigger = triggers[trigger_name] case trigger do - trigger when is_integer(trigger) and ( - (zero_indexed and trigger + 1 > 0 and trigger + 1 <= count) or - (not zero_indexed and trigger > 0 and trigger <= count) - ) -> + trigger when is_in_range(trigger, zero_indexed, 0, count) -> leds(count) |> light(color, trigger + correct_index(zero_indexed)) _triggers -> leds() diff --git a/lib/fledex/led_strip.ex b/lib/fledex/led_strip.ex index 0a22156..5abd4af 100644 --- a/lib/fledex/led_strip.ex +++ b/lib/fledex/led_strip.ex @@ -92,14 +92,14 @@ defmodule Fledex.LedStrip do end def start_link(strip_name, drivers, global_config) do - raise "Unexpected arguments #{inspect(strip_name)}, #{inspect(drivers)}, #{inspect(global_config)}" + {:error, "Unexpected arguments #{inspect(strip_name)}, #{inspect(drivers)}, #{inspect(global_config)}"} end @doc """ Define a new namespace """ @spec define_namespace(atom, atom) :: :ok | {:error, String.t()} - def define_namespace(strip_name \\ __MODULE__, namespace) do + def define_namespace(strip_name, namespace) do # Logger.info("defining namespace: #{strip_name}-#{namespace}") GenServer.call(strip_name, {:define_namespace, namespace}) end @@ -108,7 +108,7 @@ defmodule Fledex.LedStrip do Drop a previously defined namespace. """ @spec drop_namespace(atom, atom) :: :ok - def drop_namespace(strip_name \\ __MODULE__, namespace) do + def drop_namespace(strip_name, namespace) do # Logger.info("dropping namespace: #{strip_name}-#{namespace}") GenServer.call(strip_name, {:drop_namespace, namespace}) end @@ -117,7 +117,7 @@ defmodule Fledex.LedStrip do Checks whether the specified namespace already exists """ @spec exist_namespace(atom, atom) :: boolean - def exist_namespace(strip_name \\ __MODULE__, namespace) do + def exist_namespace(strip_name, namespace) do GenServer.call(strip_name, {:exist_namespace, namespace}) end @@ -130,7 +130,7 @@ defmodule Fledex.LedStrip do case some leds might retain their previously set value. """ @spec set_leds(atom, atom, list(pos_integer)) :: :ok | {:error, String.t()} - def set_leds(strip_name \\ __MODULE__, namespace, leds) do + def set_leds(strip_name, namespace, leds) do GenServer.call(strip_name, {:set_leds, namespace, leds}) end @@ -143,7 +143,7 @@ defmodule Fledex.LedStrip do """ @deprecated "will be replaced with better strip_config right from the beginning" @spec change_config(atom, list(atom), any) :: {:ok, any} - def change_config(strip_name \\ __MODULE__, config_path, value) do + def change_config(strip_name, config_path, value) do GenServer.call(strip_name, {:change_config, config_path, value}) end @@ -153,8 +153,6 @@ defmodule Fledex.LedStrip do If you do, you will surely know about it :) """ @spec reinit(atom, module | {module, keyword} | [{module, keyword}], keyword) :: :ok - def reinit(strip_name \\ __MODULE__, drivers, strip_config) - def reinit(strip_name, driver, strip_config) when is_atom(driver) do reinit(strip_name, {driver, []}, strip_config) end @@ -169,7 +167,7 @@ defmodule Fledex.LedStrip do end @spec stop(GenServer.server()) :: :ok - def stop(strip_name \\ __MODULE__) do + def stop(strip_name) do GenServer.stop(strip_name) end diff --git a/lib/fledex/utils/guards.ex b/lib/fledex/utils/guards.ex new file mode 100644 index 0000000..a4e329c --- /dev/null +++ b/lib/fledex/utils/guards.ex @@ -0,0 +1,25 @@ +# Copyright 2024, Matthias Reik +# +# SPDX-License-Identifier: Apache-2.0 +defmodule Fledex.Utils.Guards do + @moduledoc """ + This module collects all useful guards. If you want to use one of them + you need to `import` this module. + """ + + @doc """ + This guard checks whether the value is within the given range. + Notes: + + * The lower bound is excluded (except if `inverse_bounds` is true) + * The upper bound is included (except if `inverse_bounds` is true) + * This guard is not fully tested, so be careful when using that it works for you. + """ + # @spec is_in_range(integer, boolean, integer, integer) :: boolean + defguard is_in_range(value, inverse_bounds, min, max) when + is_integer(value) and + ( + (inverse_bounds and value + 1 > min and value + 1 <= max) or + (not inverse_bounds and value > min and value <= max) + ) +end diff --git a/test/fledex/driver/impl/logger_test.exs b/test/fledex/driver/impl/logger_test.exs index 7b448f8..2b3ffb4 100644 --- a/test/fledex/driver/impl/logger_test.exs +++ b/test/fledex/driver/impl/logger_test.exs @@ -66,6 +66,22 @@ defmodule Fledex.Driver.Impl.LoggerTest do assert String.contains?(log, ansi_color_b) end + test "transfer without leds" do + log = capture_log(fn -> + config = + Logger.init( + update_freq: 1, + log_color_code: false, + terminal: false + ) + + leds = [] + Logger.transfer(leds, 0, config) + end) + + assert log == "" + end + test "transfer (logger with color code)" do capture_log(fn -> config = diff --git a/test/fledex/utils/guards_test.exs b/test/fledex/utils/guards_test.exs new file mode 100644 index 0000000..6105c82 --- /dev/null +++ b/test/fledex/utils/guards_test.exs @@ -0,0 +1,47 @@ +# Copyright 2024, Matthias Reik +# +# SPDX-License-Identifier: Apache-2.0 +defmodule Fledex.Utils.GuardsTest do + use ExUnit.Case + + import Fledex.Utils.Guards + + def create_in_range_case(line) do + # IO.puts("line: #{inspect line}") + line + |> String.split(",") + |> Enum.map(fn item -> convert!(item) end) + |> List.to_tuple() + end + + def convert!("t"), do: true + def convert!("true"), do: true + def convert!("f"), do: false + def convert!("false"), do: false + def convert!(num), do: String.to_integer(num) + + describe "Test is_in_range" do + setup do + cases = File.read!("test/fledex/utils/in_range_guard_cases.csv") + |> String.split("\n") + |> Enum.reject(fn line -> + String.length(String.trim(line)) == 0 + end) + |> Enum.map(fn line -> create_in_range_case(line) end) + %{cases: cases} + end + test "test all combinations", %{cases: cases} do + Enum.each(cases, fn {value, inverted, min, max, expected} -> + # IO.puts("case #{inspect {value, inverted, min, max, expected}}") + case value do + _x when is_in_range(value, inverted, min, max) -> + # IO.puts("in_range") + assert(expected) + _x when not is_in_range(value, inverted, min, max) -> + # IO.puts("NOT in_range") + assert(not expected) + end + end) + end + end +end diff --git a/test/fledex/utils/in_range_guard_cases.csv b/test/fledex/utils/in_range_guard_cases.csv new file mode 100644 index 0000000..cd8d1f3 --- /dev/null +++ b/test/fledex/utils/in_range_guard_cases.csv @@ -0,0 +1,5 @@ +3,f,0,5,t +0,f,0,5,f +0,t,0,5,t +5,f,0,5,t +5,t,0,5,f diff --git a/test/fledex/utils/in_range_guard_cases.csv.license b/test/fledex/utils/in_range_guard_cases.csv.license new file mode 100644 index 0000000..db2df91 --- /dev/null +++ b/test/fledex/utils/in_range_guard_cases.csv.license @@ -0,0 +1,3 @@ +Copyright 2024, Matthias Reik + +SPDX-License-Identifier: Apache-2.0 \ No newline at end of file diff --git a/test/led_strip_test.exs b/test/led_strip_test.exs index ac6c6c0..dadda51 100644 --- a/test/led_strip_test.exs +++ b/test/led_strip_test.exs @@ -410,6 +410,7 @@ defmodule Fledex.LedStripTestSync do :ok = GenServer.stop(pid) assert {:ok, pid} = LedStrip.start_link(:test_strip_name5, Null, []) :ok = GenServer.stop(pid) + assert {:error, _} = LedStrip.start_link(:test_strop_name6, %{wrong: "structure"}, []) end test "client API calls", %{strip_name: strip_name} do @@ -427,6 +428,9 @@ defmodule Fledex.LedStripTestSync do test2: 123 ) + # test all 3 reinit functions (they all lead to the same result) + assert :ok == LedStrip.reinit(strip_name, Fledex.LedStripTest.TestDriver, []) + assert :ok == LedStrip.reinit(strip_name, {Fledex.LedStripTest.TestDriver, []}, []) assert :ok == LedStrip.reinit(strip_name, [{Fledex.LedStripTest.TestDriver, []}], []) assert :ok == LedStrip.drop_namespace(strip_name, @namespace) assert :ok == GenServer.stop(strip_name)