Skip to content

Commit b3e7f06

Browse files
committed
Add test fix sntp
1 parent da1c770 commit b3e7f06

File tree

5 files changed

+154
-2
lines changed

5 files changed

+154
-2
lines changed

libs/eavmlib/src/network.erl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,11 +708,15 @@ update_config(OldConfig, NewConfig) ->
708708

709709
%% @private
710710
update_opts(OldOpts, NewOpts) ->
711-
Old = maps:from_list(OldOpts),
712-
New = maps:from_list(NewOpts),
711+
Old = maps:from_list(normalize_opts(OldOpts)),
712+
New = maps:from_list(normalize_opts(NewOpts)),
713713
NewMap = maps:merge(Old, New),
714714
proplists:from_map(NewMap).
715715

716+
%% @private
717+
normalize_opts(Opts) ->
718+
[case O of A when is_atom(A) -> {A, true}; _ -> O end || O <- Opts].
719+
716720
%% @private
717721
wait_for_ip(Timeout) ->
718722
receive

src/platforms/esp32/components/avm_builtins/network_driver.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,9 @@ static void maybe_set_sntp(term sntp_config, GlobalContext *global)
591591
char *host = interop_term_to_string(interop_kv_get_value(sntp_config, host_atom, global), &ok);
592592
if (LIKELY(ok)) {
593593
// do not free(sntp)
594+
if (esp_sntp_enabled()) {
595+
esp_sntp_stop();
596+
}
594597
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
595598
esp_sntp_setservername(0, host);
596599
sntp_set_time_sync_notification_cb(time_sync_notification_cb);

src/platforms/esp32/test/main/test_erl_sources/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ compile_erlang(test_esp_partition)
6262
compile_erlang(test_esp_timer_get_time)
6363
compile_erlang(test_file)
6464
compile_erlang(test_wifi_example)
65+
compile_erlang(test_wifi_managed)
6566
compile_erlang(test_list_to_atom)
6667
compile_erlang(test_list_to_binary)
6768
compile_erlang(test_md5)
@@ -83,6 +84,7 @@ set(erlang_test_beams
8384
test_esp_timer_get_time.beam
8485
test_file.beam
8586
test_wifi_example.beam
87+
test_wifi_managed.beam
8688
test_list_to_atom.beam
8789
test_list_to_binary.beam
8890
test_md5.beam
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
%
2+
% This file is part of AtomVM.
3+
%
4+
% Copyright 2026 Peter Mindek
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+
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
%
20+
21+
-module(test_wifi_managed).
22+
23+
-export([start/0]).
24+
25+
start() ->
26+
case verify_platform(atomvm:platform()) of
27+
ok ->
28+
ok = test_managed_start(),
29+
ok = test_managed_connect(),
30+
ok = test_sta_status_lifecycle(),
31+
ok = test_disconnect_and_reconnect(),
32+
ok = test_connect_new_ap(),
33+
network:stop(),
34+
ok;
35+
Error ->
36+
Error
37+
end.
38+
39+
%% Test starting the network driver in managed mode (no immediate connection)
40+
test_managed_start() ->
41+
Self = self(),
42+
Config = [
43+
{sta, [
44+
managed,
45+
{connected, fun() -> Self ! sta_connected end},
46+
{got_ip, fun(IpInfo) -> Self ! {got_ip, IpInfo} end},
47+
{disconnected, fun() -> Self ! sta_disconnected end}
48+
]},
49+
{sntp, [
50+
{host, "time.aws.com"},
51+
{synchronized, fun sntp_synchronized/1}
52+
]}
53+
],
54+
case network:start(Config) of
55+
{ok, _Pid} ->
56+
io:format("Managed network started.~n"),
57+
%% In managed mode, sta_status should be disconnected (not connecting)
58+
disconnected = network:sta_status(),
59+
io:format("test_managed_start OK.~n"),
60+
ok;
61+
Error ->
62+
Error
63+
end.
64+
65+
%% Test connecting to an AP using sta_connect/1
66+
test_managed_connect() ->
67+
%% Status should still be disconnected before connect
68+
disconnected = network:sta_status(),
69+
ok = network:sta_connect([{ssid, "Wokwi-GUEST"}, {psk, ""}]),
70+
%% After initiating connect, status should be connecting
71+
Status = network:sta_status(),
72+
case Status of
73+
connecting -> ok;
74+
associated -> ok;
75+
connected -> ok
76+
end,
77+
ok = wait_for_ip(20000),
78+
connected = network:sta_status(),
79+
io:format("test_managed_connect OK.~n"),
80+
ok.
81+
82+
%% Test the full sta_status lifecycle
83+
test_sta_status_lifecycle() ->
84+
%% We should be connected from previous test
85+
connected = network:sta_status(),
86+
io:format("test_sta_status_lifecycle OK.~n"),
87+
ok.
88+
89+
%% Test disconnecting and reconnecting to the same AP
90+
test_disconnect_and_reconnect() ->
91+
ok = network:sta_disconnect(),
92+
ok = wait_for_disconnect(5000),
93+
disconnected = network:sta_status(),
94+
%% Reconnect using sta_connect/0 (reconnect to last AP)
95+
ok = network:sta_connect(),
96+
ok = wait_for_ip(20000),
97+
connected = network:sta_status(),
98+
io:format("test_disconnect_and_reconnect OK.~n"),
99+
ok.
100+
101+
%% Test connecting to a new AP using sta_connect/1 with sta_config
102+
test_connect_new_ap() ->
103+
ok = network:sta_disconnect(),
104+
ok = wait_for_disconnect(5000),
105+
disconnected = network:sta_status(),
106+
%% Connect again with explicit config
107+
ok = network:sta_connect([{ssid, "Wokwi-GUEST"}, {psk, ""}]),
108+
ok = wait_for_ip(20000),
109+
connected = network:sta_status(),
110+
io:format("test_connect_new_ap OK.~n"),
111+
ok.
112+
113+
sntp_synchronized({TVSec, TVUsec}) ->
114+
io:format("Synchronized time with SNTP server. TVSec=~p TVUsec=~p~n", [TVSec, TVUsec]).
115+
116+
verify_platform(esp32) ->
117+
ok;
118+
verify_platform(Platform) ->
119+
{error, {unsupported_platform, Platform}}.
120+
121+
wait_for_ip(Timeout) ->
122+
receive
123+
{got_ip, IpInfo} ->
124+
io:format("Got IP: ~p~n", [IpInfo]),
125+
ok
126+
after Timeout ->
127+
{error, timeout}
128+
end.
129+
130+
wait_for_disconnect(Timeout) ->
131+
receive
132+
sta_disconnected ->
133+
io:format("STA disconnected.~n"),
134+
ok
135+
after Timeout ->
136+
{error, timeout}
137+
end.

src/platforms/esp32/test/main/test_main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,12 @@ TEST_CASE("test_wifi_example", "[test_run]")
613613
term ret_value = avm_test_case("test_wifi_example.beam");
614614
TEST_ASSERT(ret_value == OK_ATOM);
615615
}
616+
617+
TEST_CASE("test_wifi_managed", "[test_run]")
618+
{
619+
term ret_value = avm_test_case("test_wifi_managed.beam");
620+
TEST_ASSERT(ret_value == OK_ATOM);
621+
}
616622
#endif
617623

618624
// Works C3 on local runs, but fails GH actions

0 commit comments

Comments
 (0)