Skip to content

Commit 74524ae

Browse files
value generator + test
Signed-off-by: Gabriele Ghio <gabriele.ghio@secomind.com>
1 parent dadf617 commit 74524ae

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#
2+
# This file is part of Astarte.
3+
#
4+
# Copyright 2025 SECO Mind Srl
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
defmodule Astarte.Core.Generators.Value do
20+
@moduledoc """
21+
This module provides generators for any Value type.
22+
"""
23+
use ExUnitProperties
24+
25+
alias Astarte.Core.Interface
26+
alias Astarte.Core.Mapping
27+
28+
alias Astarte.Common.Generators.DateTime, as: DateTimeGenerator
29+
alias Astarte.Common.Generators.Timestamp, as: TimestampGenerator
30+
alias Astarte.Core.Generators.Mapping, as: MappingGenerator
31+
32+
@doc """
33+
Generates a valid value based on interface
34+
"""
35+
@spec value(Interface.t()) :: StreamData.t(map())
36+
def value(%Interface{} = interface) when not is_struct(interface, StreamData) do
37+
interface |> constant() |> value()
38+
end
39+
40+
@spec value(StreamData.t(Interface.t())) :: StreamData.t(map())
41+
def value(gen) do
42+
gen all %Interface{
43+
mappings: mappings,
44+
aggregation: aggregation
45+
} <- gen,
46+
%Mapping{
47+
endpoint: endpoint
48+
} <- member_of(mappings),
49+
endpoint = interface_endpoint(aggregation, endpoint),
50+
path <- endpoint_path(endpoint),
51+
value <- build_value(aggregation, mappings) do
52+
%{
53+
path: path,
54+
value: value
55+
}
56+
end
57+
end
58+
59+
defp endpoint_path(endpoint) do
60+
endpoint
61+
|> String.split("/")
62+
|> Enum.map(&convert_token/1)
63+
|> fixed_list()
64+
|> map(&Enum.join(&1, "/"))
65+
end
66+
67+
defp convert_token(token) do
68+
case(Mapping.is_placeholder?(token)) do
69+
true -> MappingGenerator.endpoint_segment()
70+
false -> constant(token)
71+
end
72+
end
73+
74+
# TODO manage later if necessary
75+
# defp interface_reliability(%Interface{type: :properties}), do: :unique
76+
# defp interface_reliability(%Interface{mappings: [%Mapping{reliability: reliability} | _]}),
77+
# do: reliability
78+
79+
defp interface_endpoint(:individual, endpoint), do: endpoint
80+
defp interface_endpoint(:object, endpoint), do: String.replace(endpoint, ~r"/[^/]+$", "")
81+
82+
defp build_value(:individual, [%Mapping{value_type: value_type} | _]) do
83+
value_from_type(value_type)
84+
end
85+
86+
defp build_value(:object, [%Mapping{} | _] = mappings) do
87+
mappings |> Map.new(&object_value/1) |> optional_map()
88+
end
89+
90+
defp type_array(:doublearray), do: :double
91+
defp type_array(:integerarray), do: :integer
92+
defp type_array(:longintegerarray), do: :longinteger
93+
defp type_array(:booleanarray), do: :boolean
94+
defp type_array(:stringarray), do: :string
95+
defp type_array(:binaryblobarray), do: :binaryblob
96+
defp type_array(:datetimearray), do: :datetime
97+
98+
defp value_from_type(:double), do: float()
99+
defp value_from_type(:integer), do: integer(-0x7FFFFFFF..0x7FFFFFFF)
100+
defp value_from_type(:boolean), do: boolean()
101+
defp value_from_type(:longinteger), do: integer(-0x7FFFFFFFFFFFFFFF..0x7FFFFFFFFFFFFFFF)
102+
defp value_from_type(:string), do: string(:utf8, max_length: 65_535)
103+
defp value_from_type(:binaryblob), do: map(binary(max_length: 65_535), &Base.encode64/1)
104+
105+
defp value_from_type(:datetime),
106+
do:
107+
one_of([
108+
TimestampGenerator.timestamp(),
109+
DateTimeGenerator.date_time() |> map(&DateTime.to_iso8601/1)
110+
])
111+
112+
defp value_from_type(array) when is_atom(array),
113+
do: type_array(array) |> value_from_type() |> list_of(max_legth: 1023)
114+
115+
defp object_value(%Mapping{} = mapping) do
116+
%Mapping{endpoint: endpoint, value_type: value_type} = mapping
117+
{String.replace(endpoint, ~r"^.*/", ""), value_from_type(value_type)}
118+
end
119+
end

0 commit comments

Comments
 (0)