Skip to content

Commit

Permalink
astarte_appengine_api_web: add tests to Plug.GroupNameDecoder
Browse files Browse the repository at this point in the history
use of the ExUnitProperties/StreamData
(https://hexdocs.pm/stream_data/ExUnitProperties.html)
library to parameterize test writing

- use of generators (gen all) for creating cases to evaluate and checks
- execution of tests via prop tests (check all)
- added functional e2e test to "group creates the group with / in group name"
- setup test.exs and ci.exs max runs

Signed-off-by: Gabriele Ghio <[email protected]>
  • Loading branch information
shinnokdisengir committed Mar 20, 2024
1 parent 01e0fff commit 998f385
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 22 deletions.
2 changes: 1 addition & 1 deletion apps/astarte_appengine_api/.formatter.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[
import_deps: [:phoenix, :ecto, :skogsra],
import_deps: [:phoenix, :ecto, :skogsra, :stream_data],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
3 changes: 3 additions & 0 deletions apps/astarte_appengine_api/config/ci.exs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
import Config

config :stream_data,
max_runs: 1_000
3 changes: 3 additions & 0 deletions apps/astarte_appengine_api/config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ config :astarte_rpc, :amqp_connection, host: System.get_env("RABBITMQ_HOST") ||

config :astarte_appengine_api, :rpc_client, MockRPCClient

config :stream_data,
max_runs: 50

config :astarte_appengine_api,
:test_priv_key,
{%{kty: :jose_jwk_kty_rsa},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ defmodule Astarte.AppEngine.APIWeb.DeviceStatusByGroupController do
conn,
%{"realm_name" => realm_name, "group_name" => group_name, "details" => "true"} = params
) do
group_name

with {:ok, %DevicesList{} = devices_list} <-
Groups.list_detailed_devices(realm_name, group_name, params) do
render(conn, "detailed_index.json", devices_list: devices_list, request: params)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
#
# This file is part of Astarte.
#
# Copyright 2024 SECO Mind Srl
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

defmodule Astarte.AppEngine.APIWeb.Plug.GroupNameDecoder do
@moduledoc """
This plug decodes a group name, which may have been coded
This plug decodes a group name, which may have been encoded
to remove the forward slash
"""
def init(default), do: default

def call(%Plug.Conn{path_params: %{"group_name" => group_name}} = conn, _) do
%Plug.Conn{conn | path_params: %{conn.path_params | "group_name" => URI.decode(group_name)}}
put_in(conn.path_params["group_name"], URI.decode(group_name))
end

def call(conn, _), do: conn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ defmodule Astarte.AppEngine.APIWeb.Router do
end

pipeline :device_group_api do
plug Astarte.AppEngine.APIWeb.Plug.GroupNameDecoder
plug Astarte.AppEngine.APIWeb.Plug.LogGroupName
end

Expand All @@ -41,8 +42,6 @@ defmodule Astarte.AppEngine.APIWeb.Router do
plug Astarte.AppEngine.APIWeb.Plug.JoinPath
plug Astarte.AppEngine.APIWeb.Plug.LogInterface
plug Astarte.AppEngine.APIWeb.Plug.LogPath
plug Astarte.AppEngine.APIWeb.Plug.Telemetry.CallsCount
plug Astarte.AppEngine.APIWeb.Plug.GroupNameDecoder
end

pipeline :swagger do
Expand Down
8 changes: 5 additions & 3 deletions apps/astarte_appengine_api/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ defmodule Astarte.AppEngine.API.Mixfile do
{:ex_json_schema, "~> 0.7"},
{:phoenix_swagger, "~> 0.8"},
{:xandra, "~> 0.13"},
{:excoveralls, "~> 0.15", only: :test},
{:mox, "~> 0.5", only: :test},
{:pretty_log, "~> 0.1"},
{:plug_logger_with_meta, "~> 0.1"},
{:telemetry, "~> 0.4"},
Expand All @@ -108,7 +106,11 @@ defmodule Astarte.AppEngine.API.Mixfile do
{:dialyxir, "~> 1.0", only: [:dev, :ci], runtime: false},
# Workaround for Elixir 1.15 / ssl_verify_fun issue
# See also: https://github.com/deadtrickster/ssl_verify_fun.erl/pull/27
{:ssl_verify_fun, "~> 1.1.0", manager: :rebar3, override: true}
{:ssl_verify_fun, "~> 1.1.0", manager: :rebar3, override: true},
# Test section
{:excoveralls, "~> 0.15", only: :test},
{:mox, "~> 0.5", only: :test},
{:stream_data, "~> 0.5", only: :test}
]
end
end
1 change: 1 addition & 0 deletions apps/astarte_appengine_api/mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"skogsra": {:hex, :skogsra, "2.3.3", "90ea76d98ad749241b31e724ca17ed8aca0202001972aeca3cb834f44027f3ea", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}, {:yamerl, "~> 0.8", [hex: :yamerl, repo: "hexpm", optional: true]}], "hexpm", "e36880922431d41ac56d6cb4529b0526039a108fb44f8ecc90b517d494b86c28"},
"snappyer": {:hex, :snappyer, "1.2.6", "34181e3233f68a92044e176fe96e54fee7957acc2be554f0460d799c495166c2", [:rebar3], [], "hexpm", "d538d1e8892af09dc8b2771b2652c9d70f009cd1556246b3e22706df643f47b4"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"},
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.0", "da9d49ee7e6bb1c259d36ce6539cd45ae14d81247a2b0c90edf55e2b50507f7b", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5cfe67ad464b243835512aa44321cee91faed6ea868d7fb761d7016e02915c3d"},
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "0.4.2", "9c5b2cce20222f3c16256dcd6cfaf59d05a84dc664060ab938c6ac40e91d05e0", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.5", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "9cd707328a1971c886993f3e4b22c68835153efa674bf31a957b30439de9b258"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#

defmodule Astarte.AppEngine.APIWeb.GroupsControllerTest do
use ExUnitProperties
use Astarte.AppEngine.APIWeb.ConnCase

alias Astarte.AppEngine.API.DatabaseTestHelper
Expand All @@ -25,6 +26,7 @@ defmodule Astarte.AppEngine.APIWeb.GroupsControllerTest do
alias Astarte.AppEngine.API.Device.DevicesList
alias Astarte.AppEngine.API.Device.DeviceStatus
alias Astarte.AppEngine.API.Groups
alias Astarte.AppEngine.API.GroupTestGenerator

@realm "autotestrealm"
@group_name "mygroup"
Expand Down Expand Up @@ -171,22 +173,24 @@ defmodule Astarte.AppEngine.APIWeb.GroupsControllerTest do
assert json_response(create_again_conn, 409)["errors"] != nil
end

test "creates the group with / in group name", %{conn: conn} do
group_name = "world/europe/italy"
encoded_group_name = "world%2Feurope%2Fitaly"
@tag issue: 904
property "creates the group with / in group name", %{conn: conn} do
check all group_name <- GroupTestGenerator.group_name() do
params = %{
"group_name" => group_name,
"devices" => @group_devices
}

params = %{
"group_name" => group_name,
"devices" => @group_devices
}
create_conn = post(conn, groups_path(conn, :create, @realm), data: params)

create_conn = post(conn, groups_path(conn, :create, @realm), data: params)
assert json_response(create_conn, 201)["data"] == params,
"Failed to create group #{group_name}"

assert json_response(create_conn, 201)["data"] == params

show_conn = get(conn, groups_path(conn, :show, @realm, encoded_group_name))
show_conn = get(conn, groups_path(conn, :show, @realm, group_name))

assert json_response(show_conn, 200)["data"]["group_name"] == group_name
assert json_response(show_conn, 200)["data"]["group_name"] == group_name,
"Failed post/get same group_name #{group_name}"
end
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#
# This file is part of Astarte.
#
# Copyright 2024 SECO Mind Srl
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

defmodule Astarte.AppEngine.APIWeb.Plug.GroupNameDecoderTest do
use Astarte.AppEngine.APIWeb.ConnCase
use ExUnitProperties
alias Astarte.AppEngine.APIWeb.Plug.GroupNameDecoder
alias Astarte.AppEngine.API.GroupTestGenerator

@max_subpath_count 10

@tag issue: 904
property "call/2 decode path" do
check all raw <- GroupTestGenerator.group_name() do
conn = build_conn()
# Normally, phx does encoding
encoded =
raw
|> URI.encode()

request =
put_in(
conn.path_params["group_name"],
encoded
)

%{path_params: %{"group_name" => check}} =
request
|> GroupNameDecoder.call(nil)

assert check == raw,
"The group name #{encoded} cannot be decoded back to its original value"
end
end
end
43 changes: 43 additions & 0 deletions apps/astarte_appengine_api/test/support/generators/group.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#
# This file is part of Astarte.
#
# Copyright 2024 SECO Mind Srl
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

defmodule Astarte.AppEngine.API.GroupTestGenerator do
@moduledoc """
Helpers group's generators
"""
use ExUnitProperties

@max_subpath_count 10
@max_subpath_length 20

@doc """
Generate a random group name
Es.
world/europe/italy
"""
def group_name do
string(:ascii, min_length: 1, max_length: @max_subpath_length)
|> uniq_list_of(
min_length: 1,
max_length: @max_subpath_count
)
|> filter(fn [<<first, _::binary>> | _] ->
first not in [?@, ?~, ?\s]
end)
|> map(&Enum.join(&1, "/"))
end
end

0 comments on commit 998f385

Please sign in to comment.