Skip to content

Commit

Permalink
refactoring test suite using StreamData
Browse files Browse the repository at this point in the history
TODO
- completed valid generators

Signed-off-by: Gabriele Ghio <[email protected]>
  • Loading branch information
shinnokdisengir committed Apr 5, 2024
1 parent 20fa298 commit ac30b5e
Show file tree
Hide file tree
Showing 14 changed files with 800 additions and 1 deletion.
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Astarte.AppEngine.API.ExampleTest do
use ExUnit.Case, async: true
use ExUnitProperties
use Astarte.Test.Cases.Database
use Astarte.Test.Cases.Conn

alias Astarte.Test.Setups.Database, as: DatabaseSetup
alias Astarte.Test.Setups.Conn, as: ConnSetup

# @moduletag :v2
describe "db smoke" do
# setup single test fixtures
setup [
{ConnSetup, :request_path}
]

property "realm exists", %{conn: conn, cluster: cluster, realm: realm} do
with {:ok, prepared} <- Xandra.Cluster.prepare(cluster, "DESCRIBE TABLES;"),
{:ok, %Xandra.Page{} = page} <- Xandra.Cluster.execute(cluster, prepared),
do: Enum.to_list(page) |> IO.inspect()

:ok
# check all {first, second, third} <- NumbersGenerator.random_numbers(max_value) do
# assert true
# end
end

test "no token returns 401", %{conn: conn, request_path: request_path} do
conn = get(conn, request_path)
assert json_response(conn, 401)["errors"]["detail"] == "Unauthorized"
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
defmodule Astarte.AppEngine.API.StatsV2Test do
use ExUnit.Case, async: true
use ExUnitProperties
use Astarte.Test.Cases.Database
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: DatabaseSetups
alias Astarte.Test.Generators.Strings, as: StringGenerator
alias Astarte.Test.Generators.Interfaces, as: InterfaceGenerator
alias Astarte.Test.Generators.Mappings, as: MappingGenerator

describe "validation generators" do
# setup [{DatabaseSetups, :setup_devices}]

@tag :v2
property "validate interface" do
check all interface <- InterfaceGenerator.interface() do
%Changeset{valid?: valid, errors: errors} = Interface.changeset(interface)
assert valid
end
end
end

describe "get_devices_stats" do
setup [{DatabaseSetups, :setup_devices}]

# @tag :v2
property "return correct response on get_devices_stats", %{
realm: realm,
devices: devices
} do
check all {realm_name, valid} <-
frequency([
{1, tuple({realm, true})},
{1, tuple({StringGenerator.realm_name(), constant(false)})}
]) do
if valid do
assert {:ok, %DevicesStats{} = stats} = Stats.get_devices_stats(realm_name)
# assert stats.total_devices == DatabaseTestHelper.devices_count()
# assert stats.connected_devices == 0
else
assert {:error, _reason} = Stats.get_devices_stats(realm_name)
end
end
end

# test "returns an error for unexisting realm" do
# assert {:error, _reason} = Stats.get_devices_stats("unexisting")
# end
end

# setup do
# DatabaseTestHelper.seed_data()
# end

# describe "get_devices_stats" do
# test "returns an error for unexisting realm" do
# assert {:error, _reason} = Stats.get_devices_stats("unexisting")
# end

# test "returns the correct stats for the autotestrealm" do
# assert {:ok, %DevicesStats{} = stats} = Stats.get_devices_stats("autotestrealm")

# assert stats.total_devices == DatabaseTestHelper.devices_count()
# assert stats.connected_devices == 0
# end

# test "gets updated connected count after device connection" do
# assert {:ok, %DevicesStats{connected_devices: 0}} = Stats.get_devices_stats("autotestrealm")

# DatabaseTestHelper.fake_connect_device("f0VMRgIBAQAAAAAAAAAAAA", true)

# assert {:ok, %DevicesStats{connected_devices: 1}} = Stats.get_devices_stats("autotestrealm")

# DatabaseTestHelper.fake_connect_device("f0VMRgIBAQAAAAAAAAAAAA", false)

# assert {:ok, %DevicesStats{connected_devices: 0}} = Stats.get_devices_stats("autotestrealm")
# end
# end
end
20 changes: 20 additions & 0 deletions apps/astarte_appengine_api/test/support_v2/cases/conn.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule Astarte.Test.Cases.Conn do
use ExUnit.CaseTemplate

using do
quote do
import Plug.Conn
import Phoenix.ConnTest
import Astarte.AppEngine.APIWeb.Router.Helpers

# The default endpoint for testing
@endpoint Astarte.AppEngine.APIWeb.Endpoint
end
end

alias Astarte.Test.Setups.Conn, as: ConnSetup

setup_all [
{ConnSetup, :create_conn}
]
end
15 changes: 15 additions & 0 deletions apps/astarte_appengine_api/test/support_v2/cases/database.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
defmodule Astarte.Test.Cases.Database do
use ExUnit.CaseTemplate

using do
quote do
end
end

alias Astarte.Test.Setups.Database, as: DatabaseSetup

setup_all [
{DatabaseSetup, :connect_db},
{DatabaseSetup, :setup_db}
]
end
Empty file.
59 changes: 59 additions & 0 deletions apps/astarte_appengine_api/test/support_v2/generators/entites.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
defmodule Astarte.Test.Generators.Entities do
use ExUnitProperties

def domain() do
gen all first <- string([?a..?z], length: 3),
second <- string([?a..?z, ?A..?Z], min_length: 1, max_length: 10),
third <- string([?a..?z, ?A..?Z], min_length: 1, max_length: 10) do
first <> "." <> second <> "." <> third
end
end

def interface() do
gen all domain <- domain(),
enabled <- boolean() do
{domain, enabled}
end
end

def interface_value() do
gen all interface <- interface(),
value <- integer(1..100_100) do
{interface, value}
end
end

def interfaces() do
gen all interface_value <- list_of(interface_value()),
num <- integer(0..20) do
Enum.take(interface_value, num) |> Map.new()
end
end

def options do
optional_map(%{
display_name: string(:alphanumeric),
serial: string(?0..?9, min_length: 1, max_length: 10)
})
end

def attributes do
fixed_map(%{
attribute_key: string(:alphanumeric)
})
end

def device() do
gen all id <- string(:alphanumeric, length: 22),
value <- integer(0..8_000_000),
interfaces <- one_of([nil, interfaces()]),
options <- one_of([nil, options()]),
attributes <- attributes() do
{id, value, interfaces, options, attributes}
end
end

def devices() do
list_of(device())
end
end
124 changes: 124 additions & 0 deletions apps/astarte_appengine_api/test/support_v2/generators/interfaces.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
defmodule Astarte.Test.Generators.Interfaces do
use ExUnitProperties

alias Astarte.Core.Interface
alias Astarte.Test.Generators.Strings, as: StringsGenerator
alias Astarte.Test.Generators.Mappings, as: MappingsGenerator

defp name() do
string(:alphanumeric, min_length: 1, max_length: 16)
|> list_of(
min_length: 2,
max_length: 5
)
|> filter(fn [<<first, _::binary>> | _] ->
first < 48 or first > 57
end)
|> map(&Enum.join(&1, "."))
end

defp versions() do
gen all major_version <- integer(0..9),
minor_version <- integer(0..255) do
case {major_version, minor_version} do
{0, 0} -> {0, 1}
valid -> valid
end
end
end

defp type() do
[
:datastream,
:properties
]
|> Enum.map(&constant/1)
|> one_of()
end

defp ownership() do
[
:device,
:server
]
|> Enum.map(&constant/1)
|> one_of()
end

defp mappings(config) do
uniq_list_of(MappingsGenerator.mapping(config), min_length: 1, max_length: 1000)
end

defp aggregation(%{type: :properties}) do
constant(:individual)
end

defp aggregation(_) do
[
:individual,
:object
]
|> Enum.map(&constant/1)
|> one_of()
end

defp description() do
string(:ascii, min_length: 1, max_length: 1000)
end

defp doc() do
string(:ascii, min_length: 1, max_length: 100_000)
end

defp required_fields() do
gen all name <- name(),
{major_version, minor_version} <- versions(),
type <- type(),
aggregation <- aggregation(%{type: type}),
ownership <- ownership(),
prefix <- StringsGenerator.endpoint_prefix(),
retention <- MappingsGenerator.retention(),
reliability <- MappingsGenerator.reliability(),
expiry <- MappingsGenerator.expiry(),
allow_unset <- MappingsGenerator.allow_unset(),
explicit_timestamp <- MappingsGenerator.explicit_timestamp(),
mappings <-
mappings(%{
aggregation: aggregation,
prefix: prefix,
retention: retention,
reliability: reliability,
expiry: expiry,
allow_unset: allow_unset,
explicit_timestamp: explicit_timestamp
}) do
%{
name: name,
interface_name: name,
major_version: major_version,
minor_version: minor_version,
version_major: major_version,
version_minor: minor_version,
type: type,
interface_type: type,
ownership: ownership,
aggregation: aggregation,
mappings: mappings
}
end
end

defp optional_fields() do
optional_map(%{
description: description(),
doc: doc()
})
end

def interface() do
gen all required <- required_fields(),
optional <- optional_fields() do
struct(Interface, Map.merge(required, optional))
end
end
end
Loading

0 comments on commit ac30b5e

Please sign in to comment.