In certain cases the autoconnect portion of each subtest was connecting
to the network so fast that the check for obj.scanning was never successful
since IWD was already connected (and in turn not scanning). Since the
autoconnect path will wait for the device to be connected there really isn't
a reason to wait for any scanning conditions. The normal connect path does
need to wait for scanning though, and for this we can now use the new
scan_if_needed parameter to get_ordered_networks.
There is a very common block of code inside many autotests
which goes something like:
device.scan()
condition = 'obj.scanning'
wd.wait_for_object_condition(device, condition)
condition = 'not obj.scanning'
wd.wait_for_object_condition(device, condition)
network = device.get_ordered_network('an-ssid')
When you see the same pattern in nearly all the tests this shows
we need a helper. Basic autotests which merely check that a
connection succeeded should not need to write the same code again
and again. This code ends up being copy-pasted which can lead to
bugs.
There is also a code pattern which attempts to get ordered
networks, and if this fails it scans and tries again. This, while
not optimal, does prevent unneeded scanning by first checking if
any networks already exist.
This patch solves both the code reuse issue as well as the recovery
if get_ordered_network(s) fails. A new optional parameter was
added to get_ordered_network(s) which is False by default. If True
get_ordered_network(s) will perform a scan if the initial call
yields no networks. Tests will now be able to simply call
get_ordered_network(s) without performing a scan before hand.
These values were meant only to force IWD's BSS preference but
since the RSSI's were so low in some cases this caused a roam
immediately after connecting. This patch changes the RSSI values
to prevent a roam from happening.
'Connected' property of the network object is set before the connection
attempt is made and does not indicate a connection success. Therefore,
use device status property to identify the connection status of the device.
This test made it past the initial refactor to use HostapdCLI with the
'config' parameter. This avoids the need to iterate the hostapd map in
the actual test.
This test merely verifies hostapd receieved our measurement reports
and verified they were valid. Hostapd does not verify the actual
beacon report body. Really, the only way to test this is on an
actual network which makes these requests.
Hostapd has a feature where you can connect to its control socket and
receive events it generates. Currently we only send commands via this
socket.
First we open the socket (/var/run/hostapd/<iface>) and send the
ATTACH command. This tells hostapd we are ready and after this any
events will be sent over this socket.
A new API, wait_for_event, was added which takes an event string and
waits for some timeout. The glib event loop has been integrated into
this, though its not technically async since we are selecting over a
socket which blocks. To mitigate this a small timeout was chosen for
each select call and then wrapped in a while loop which waits for the
full timeout.
Its difficult to know 100%, but this random test failures appeared
to be caused by two issues. One was that get_ordered_network is being
checked for None, when it was returning a zero length array. Because
of this the scanning block was never executed in any cases. This was
fixed in the previous commit. The other issue was the disconnect at
the start of the tests. The disconnect will cause all pending scans
to cancel, which appeared to cause the scanning block below to be
skipped over quickly if the timing was right. Then, afterwards,
getting a single network failed because scanning was not complete.
If no networks are found, return None rather than an empty
array. This is easier to check by the caller (and was assumed
in some cases). Also add an exception to get_ordered_network
if no network is found.
If the config file passed in is not found we would continue and
eventually something else would fail. Instead immediately raise an
exception to be more clear on what is actually failing.
This autotest was manually creating the .known_network.freq file so
the UUID needed to be manually generated and updated for the test
to function correctly.
This is merely an empty test that can act as a sandbox for the new
--shell command. It was not named with 'test' so that autotesting
will skip it.
This test is not very useful for virtual hardware testing
(mac80211_hwsim), but very useful for USB/PCI passthrough. When
setup correctly, you can now pass through a single device and test
against real networks with a minimal kernel.
Doing this scan causes issues in the test. Like with other autoconnect
tests we can just use the fact that IWD will always be doing a periodic
scan during start up, so we only need to wait for that to finish before
querying the network list.
Initially the solution to copying files to .hotspot was to use the
existing copy_to_storage, but allow full directory copying. Doing it
this way does not allow us to copy single files into .hotspot which
makes it difficult to test single configurations in several consecutive
tests.
This adds a new API, copy_to_hotspot, where a single hotspot config
can be provided. clear_storage was also modified to clear out the
.hotspot directory in addition to the regular storage directory.
This removes all the duplicated code where the interfaces are iterated
and the radio/hostapd instances are created. Instead the two new APIs
are used to get each instance, e.g.:
hapd = HostapdCLI(config='ssid.conf')
radio = hwsim.get_radio('radX')
There is a common interface lookup in many tests in order to initialize
the HostapdCLI object e.g.:
for intf in hostapd_map.values():
if intf.config == 'ssidOWE.conf':
hapd = HostapdCLI(intf)
break
Instead of having to do this in every test, HostapdCLI will now
optionally take a config file (config=<file>). The interface object
will still be prefered (i.e. supplying an interface will not even
check the config file) as to not break existing tests. But if only
a config file is supplied the lookup is done internally.
There are some tests that do still need the interface, as they do
an interface lookup to initialize both hostapd and hwsim at the
same time.
The start_ap method was raising potential dbus errors before converting
them to an IWD error type. This is due to dbus.Set() not taking an error
handler. The only way to address this is to catch the error, convert it
and raise the converted error.
Running autotests with native hardware will not work on tests which
depend on the hwsim python API (since hwsim will not be running).
For these tests, it will now be required that they specify:
needs_hwsim=1
This allows the test to be skipped when running with native hardware
rather than the test failing with a python exception.
This new test was merged during the time when testutil was not working
properly, so it was never verified to work with respect to testutil
(testing for 'connected' has always worked).
Since testFILS has 2 hostapd interfaces test_interface_connected was
defaulting to the incorrect interface for the SHA384 test. Now, the
explicit interfaces are passed in when checking for connectivity.
Don't use del wd to dereference the IWD instance at the end of the function
where it has been defined in the first place as at this point wd is about
to have its reference count decreased anyway (the variable's scope is
ending) so it's pointless (but didn't hurt).
Relying on the __del__ destructor to kill the IWD process in those tests
it has been started in the constructor is a bit of a hack in the first
place, because the destructor is called on garbage collection and even
through CPython does this on the refcount reaching 0, this is not
documented and there's no guideline on when it should happen or if it
should happen at all. So it could be argued that we should keep the del
wd statemenets to be able to easily replace all of them with a call to a
new method. But most of them are not placed so that they're guaranteed
to happen on test success or failure. It would probably be easier to do
this and other housekeeping in a base class and make the tests its
subclasses. Also some of these tests don't really need to launch iwd
themselves, since IWD now tracks changes in the known network files I
think IWD only really needs to be killed between tests when main.conf
changes.
In the tests that only want to iterate over the hostapd interfaces,
simplify the pattern of walking through the whole wiphy_map tree by
instead using the hostapd_map variable which is already filtered to only
contain hostapd interfaces.
For the interface connectivity tests obtain the lists of interfaces in
use directly from the IWD class, which has the current list from DBus
properties.
The hostapd_map dictionary is indexed by the interface name so there's
no point iterating over it to find that entry whose name matches, we can
look up by the name directly. Simplify code.
In the test utilties updated the wiphy_map struct built from the
TEST_WIPHY_LIST variable to parse the new format and to use a new
structure where each wiphy is a namedtuple and each interface under it
also contains a reference to that wiphy. The 'use' field is now
assigned to the wiphy instead of to the interface.
The AdHoc methods used to miss the change in properties
on AdHoc interface. To address the race condition, we
subscribe 'PropertiesChanged' signal first and then do
GetAll properties call. This way we are not missing
'PropertiesChanged' signal in between these calls.
Previously, the WPS tests have shared a single instance of iwd
among themselves. This approach didn’t allow to identify which
tests have passed and which failed. The new solution makes WPS
tests independent from each other by creating a new instance
of iwd for each one of them.
The simplest way to test this was to create a new AP, where
max_num_sta=1. This only allows a single STA to connect to this AP.
We connect a device to this AP, then try and connect with another.
This results in hostapd failing with DENIED_NO_MORE_STAS, which will
cause a temporary blacklist. We can then disconnect both devices,
and reconnect the device that previously got denied. If it connects
then we know the blacklist only persisted for that earlier connection.