Skip to content

Commit

Permalink
Cleaning up the function guards in the dot component
Browse files Browse the repository at this point in the history
Adding additional unit tests to go back towards 100% coverage.
Fixing a bug in the LedStrip. We shouldn't raise an exception, but only return an error if the arguments are wrong
BREAKING CHANGE: Removing the default strip_name from the LedStrip. You have to explicitly pass a name. You can simply pass in LedStrip instead of nothing to get the same behaviour
  • Loading branch information
a-maze-d committed Aug 5, 2024
1 parent b89670a commit fe63974
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 13 deletions.
6 changes: 2 additions & 4 deletions lib/fledex/component/dot.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand Down
16 changes: 7 additions & 9 deletions lib/fledex/led_strip.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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
Expand All @@ -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

Expand Down
25 changes: 25 additions & 0 deletions lib/fledex/utils/guards.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2024, Matthias Reik <fledex@reik.org>
#
# 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
16 changes: 16 additions & 0 deletions test/fledex/driver/impl/logger_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
47 changes: 47 additions & 0 deletions test/fledex/utils/guards_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2024, Matthias Reik <fledex@reik.org>
#
# 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
5 changes: 5 additions & 0 deletions test/fledex/utils/in_range_guard_cases.csv
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions test/fledex/utils/in_range_guard_cases.csv.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Copyright 2024, Matthias Reik <fledex@reik.org>

SPDX-License-Identifier: Apache-2.0
4 changes: 4 additions & 0 deletions test/led_strip_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down

0 comments on commit fe63974

Please sign in to comment.