Skip to content

Commit

Permalink
Refactoring test 2.0
Browse files Browse the repository at this point in the history
Changed
- using exandra -- waiting for database project
- implemented jwt + public/private key
- wip group tests
- squashed all failure
- polishing
- removed one_of_constant -> member_of
- splitted tests
- WIP device generator
- completed device generator...but using opaque data (TODO change it)
- basic datetime generator
- WIP device generator
- using Keyword.validate!
- WIP insert into db, IPNET error
- completed device WIP id doesn't match
- completed base tests device
- polishing
- renamed realm -> keyspace
- completed group generator + setup + case
- wip group test (group_name "!" doesn't work)
- added encoded_id field to device test
- unlinked Conn <-> Database cases
- fixed realm name
- fixed valid group name test
- added already exists
- polished
- removed common.ex

Signed-off-by: Gabriele Ghio <gabriele.ghio@secomind.com>
  • Loading branch information
shinnokdisengir committed Aug 13, 2024
1 parent 20fa298 commit ef71037
Show file tree
Hide file tree
Showing 26 changed files with 2,126 additions and 4 deletions.
2 changes: 1 addition & 1 deletion apps/astarte_appengine_api/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ defmodule Astarte.AppEngine.API.Mixfile do
end

# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["test/support", "lib"]
defp elixirc_paths(:test), do: ["test/support", "test/support_v2", "lib"]
defp elixirc_paths(_), do: ["lib"]

defp dialyzer_cache_directory(:ci) do
Expand Down
9 changes: 6 additions & 3 deletions apps/astarte_appengine_api/mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
"cqex": {:hex, :cqex, "1.0.1", "bc9980ac3b82d039879f8d6ca589deab799fe08f80ff449d60ad709f2524718f", [:mix], [{:cqerl, "~> 2.0.1", [hex: :cqerl, repo: "hexpm", optional: false]}], "hexpm", "1bbf2079c044cbf0f747f60dcf0409a951eaa8f1a2447cd6d80d6ff1b7c4dc6b"},
"credentials_obfuscation": {:hex, :credentials_obfuscation, "3.4.0", "34e18b126b3aefd6e8143776fbe1ceceea6792307c99ac5ee8687911f048cfd7", [:rebar3], [], "hexpm", "738ace0ed5545d2710d3f7383906fc6f6b582d019036e5269c4dbd85dbced566"},
"cyanide": {:hex, :cyanide, "2.0.0", "f97b700b87f9b0679ae812f0c4b7fe35ea6541a4121a096cf10287941b7a6d55", [:mix], [], "hexpm", "7f9748251804c2a2115b539202568e1117ab2f0ae09875853fb89cc94ae19dd1"},
"db_connection": {:hex, :db_connection, "2.3.1", "4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"},
"decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"},
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"},
"dialyzex": {:git, "https://github.com/Comcast/dialyzex.git", "cdc7cf71fe6df0ce4cf59e3f497579697a05c989", []},
"ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"},
"ecto_morph": {:hex, :ecto_morph, "0.1.28", "073c3faf4ff7c496fc2ae8352ea7d8c9b89ae7b2e6995da3027454d44cb547fb", [:mix], [{:ecto, ">= 3.0.3", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "ce39a1252a5b7d58c601beb702eed4303b11016705f02fbae9b78f8fb971b0bc"},
"ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"},
"elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_json_schema": {:hex, :ex_json_schema, "0.7.4", "09eb5b0c8184e5702bc89625a9d0c05c7a0a845d382e9f6f406a0fc1c9a8cc3f", [:mix], [], "hexpm", "45c67fa840f0d719a2b5578126dc29bcdc1f92499c0f61bcb8a3bcb5935f9684"},
"ex_lttb": {:hex, :ex_lttb, "0.3.0", "aec7aab96be6535c4c8f143c2b5f2191a9d1a6f512690ec6d6f4f6bce0223b0f", [:mix], [], "hexpm", "6937bf70307d85781200912c3dcf5e32efdcbdf958e9107ee0a61d4fefc1fddb"},
"exandra": {:hex, :exandra, "0.10.2", "e95dca77501df9ae48f23854224e91712e64d65cd7157e2fe46232ea97918ec6", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:xandra, "~> 0.18.0", [hex: :xandra, repo: "hexpm", optional: false]}], "hexpm", "334616b170233828f2acac0b060c3c6c91051848972218d2b159e3a455b07c84"},
"excoveralls": {:hex, :excoveralls, "0.15.0", "ac941bf85f9f201a9626cc42b2232b251ad8738da993cf406a4290cacf562ea4", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9631912006b27eca30a2f3c93562bc7ae15980afb014ceb8147dc5cdd8f376f1"},
"expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"},
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
Expand All @@ -41,6 +43,7 @@
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"},
"nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"},
"observer_cli": {:hex, :observer_cli, "1.6.1", "d176f967c978ab8b8a29c35c12524f78b7bb36fd4e9b8276dd75c9cb56e07e42", [:mix, :rebar3], [{:recon, "~>2.5.1", [hex: :recon, repo: "hexpm", optional: false]}], "hexpm", "3418e319764b9dff1f469e43cbdffd7fd54ea47cbf765027c557abd146a19fb3"},
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
"phoenix": {:hex, :phoenix, "1.7.2", "c375ffb482beb4e3d20894f84dd7920442884f5f5b70b9f4528cbe0cedefec63", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.4", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "1ebca94b32b4d0e097ab2444a9742ed8ff3361acad17365e4e6b2e79b4792159"},
Expand Down Expand Up @@ -74,5 +77,5 @@
"uuid": {:hex, :uuid_erl, "2.0.1", "1fd9079c544d521063897887a1c5b3302dca98f9bb06aadcdc6fb0663f256797", [:rebar3], [{:quickrand, "~> 2.0.1", [hex: :quickrand, repo: "hexpm", optional: false]}], "hexpm", "ab57caccd51f170011e5f444ce865f84b41605e483a9efcc468c1afaec87553b"},
"websock": {:hex, :websock, "0.5.1", "c496036ce95bc26d08ba086b2a827b212c67e7cabaa1c06473cd26b40ed8cf10", [:mix], [], "hexpm", "b9f785108b81cd457b06e5f5dabe5f65453d86a99118b2c0a515e1e296dc2d2c"},
"websock_adapter": {:hex, :websock_adapter, "0.5.1", "292e6c56724e3457e808e525af0e9bcfa088cc7b9c798218e78658c7f9b85066", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "8e2e1544bfde5f9d0442f9cec2f5235398b224f75c9e06b60557debf64248ec1"},
"xandra": {:hex, :xandra, "0.13.1", "f82866e6c47527f74f35dd3007b5311121852dd861a29ed1613e27ccfaba0102", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.7", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "a2efdb8921e3b694bf3505e40c5ec9d353d8fa3755cec946be7c18b8236d7230"},
"xandra": {:hex, :xandra, "0.18.1", "6ac8794161f69a5ada6e8c197e5e3472f44c94f7b3add208cd3abc8ee135f852", [:mix], [{:decimal, "~> 1.7 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "25d74d8101ca303b7be102da14a37629ae94c1bd21827f9d199a27f5e89b785f"},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#
# 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.V2DeviceTest do
use ExUnit.Case, async: true
use ExUnitProperties
use Astarte.Test.Cases.Device

alias Ecto.Changeset
alias StreamData
alias Astarte.Core.Mapping
alias Astarte.Core.Interface
alias Astarte.AppEngine.API.Stats
alias Astarte.AppEngine.API.Stats.DevicesStats
alias Astarte.Test.Setups.Database, as: DatabaseSetup
alias Astarte.Test.Setups.Interface, as: InterfaceSetup
alias Astarte.Test.Generators.String, as: StringGenerator
alias Astarte.Test.Generators.Interface, as: InterfaceGenerator
alias Astarte.Test.Generators.Mapping, as: MappingGenerator
alias Astarte.Test.Generators.Device, as: DeviceGenerator
alias Astarte.Test.Helpers.Database, as: DatabaseHelper

@moduletag :v2
@moduletag :device
@moduletag interface_count: 10
@moduletag device_count: 100

describe "device generator testing" do
property "validate device with pre-generated interfaces", %{interfaces: interfaces} do
check all device <- DeviceGenerator.device(interfaces: interfaces) do
:ok
end
end
end

describe "devices fixtures testing" do
test "validate inserted devices", %{
cluster: cluster,
keyspace: keyspace,
devices: devices
} do
list = DatabaseHelper.select!(:device, cluster, keyspace, devices)
fields = [:device_id, :encoded_id]

for field <- fields do
f = fn l -> Enum.map(l, fn d -> d[field] end) end
devices_ids_a = f.(devices)
devices_ids_b = f.(list)
assert [] === devices_ids_a -- devices_ids_b
assert [] === devices_ids_b -- devices_ids_a
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#
# 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.V2GroupTest do
use ExUnit.Case, async: true
use ExUnitProperties
use Astarte.Test.Cases.Group
use Astarte.Test.Cases.Conn

alias Astarte.AppEngine.API.Device
alias Astarte.AppEngine.API.Device.DevicesList
alias Astarte.AppEngine.API.Device.DeviceStatus
alias Astarte.Test.Generators.Group, as: GroupGenerator
alias Astarte.Test.Generators.Device, as: DeviceGenerator

@moduletag :v2
@moduletag :group
@moduletag interface_count: 10
@moduletag device_count: 100
@moduletag group_count: 2

describe "create" do
@tag :unit
property "fails when group name is not valid", %{auth_conn: auth_conn, keyspace: keyspace} do
check all {{group_name, error}, devices} <-
tuple({
bind(GroupGenerator.name(), fn name ->
bind(integer(0..2), fn num ->
constant(
case num do
0 -> {"", "can't be blank"}
1 -> {"~" <> name, "is not valid"}
2 -> {"@" <> name, "is not valid"}
end
)
end)
end),
list_of(DeviceGenerator.encoded_id(), min_length: 0, max_length: 1)
}) do
params = %{
"group_name" => group_name,
"devices" => devices
}

response = post(auth_conn, groups_path(auth_conn, :create, keyspace), data: params)
assert [error] === json_response(response, 422)["errors"]["group_name"]
end
end

property "fails when devices list empty", %{auth_conn: auth_conn, keyspace: keyspace} do
@tag :unit
check all group_name <- GroupGenerator.name() do
params = %{
"group_name" => group_name,
"devices" => []
}

response = post(auth_conn, groups_path(auth_conn, :create, keyspace), data: params)

assert ["should have at least 1 item(s)"] ===
json_response(response, 422)["errors"]["devices"]
end
end

property "fails when device does not exist", %{auth_conn: auth_conn, keyspace: keyspace} do
check all group_name <- GroupGenerator.name(),
devices <- list_of(DeviceGenerator.encoded_id(), min_length: 1) do
params = %{
"group_name" => group_name,
"devices" => devices
}

response = post(auth_conn, groups_path(auth_conn, :create, keyspace), data: params)

assert ["must exist (#{Enum.at(devices, 0)} not found)"] ===
json_response(response, 422)["errors"]["devices"]
end
end

test "fails when the group already exists", %{
auth_conn: auth_conn,
cluster: cluster,
keyspace: keyspace,
interfaces: interfaces,
devices: devices,
groups: groups
} do
device_ids = Enum.map(devices, & &1.encoded_id)
existing_group_name = Enum.at(groups, 0).name

params = %{
"group_name" => existing_group_name,
"devices" => device_ids
}

response = post(auth_conn, groups_path(auth_conn, :create, keyspace), data: params)
assert "Group already exists" === json_response(response, 409)["errors"]["detail"]
end

property "success creates groups with valid parameters", %{
auth_conn: auth_conn,
cluster: cluster,
keyspace: keyspace,
interfaces: interfaces,
devices: devices,
groups: groups
} do
device_ids = Enum.map(devices, & &1.encoded_id)
old_group_names = Enum.map(groups, & &1.name)

check all group_name <-
filter(GroupGenerator.name(), fn name -> name not in old_group_names end) do
params = %{
"group_name" => group_name,
"devices" => device_ids
}

response = post(auth_conn, groups_path(auth_conn, :create, keyspace), data: params)
assert params === json_response(response, 201)["data"]
response = get(auth_conn, groups_path(auth_conn, :show, keyspace, group_name))
assert group_name === json_response(response, 200)["data"]["group_name"]

for device <- device_ids do
{:ok, %DeviceStatus{groups: groups}} = Device.get_device_status!(keyspace, device)
assert group_name in groups
# TODO right way
# assert [group_name] === groups -- old_group_names
end
end
end
end
end
Loading

0 comments on commit ef71037

Please sign in to comment.