Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions tests/l2Test/libnm/l2_test_libnmproxyWifi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2251,6 +2251,146 @@ TEST_F(NetworkManagerWifiTest, RemoveKnownSSIDs_success_ssid_specified_found)
g_ptr_array_free(fakeDevices, TRUE);
}

TEST_F(NetworkManagerWifiTest, ActivateKnownConnection_WifiConnectionTypeFiltering)
{
GPtrArray* fakeDevices = g_ptr_array_new();
NMDevice *deviceDummy = static_cast<NMDevice*>(g_object_new(NM_TYPE_DEVICE_WIFI, NULL));
g_ptr_array_add(fakeDevices, deviceDummy);

// Create multiple connections with different types
GPtrArray* dummyConns = g_ptr_array_new();
NMConnection *wifiConn = reinterpret_cast<NMConnection*>(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL));
NMConnection *ethConn = reinterpret_cast<NMConnection*>(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL));
NMConnection *vpnConn = reinterpret_cast<NMConnection*>(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL));
g_ptr_array_add(dummyConns, ethConn); // First connection is ethernet
g_ptr_array_add(dummyConns, wifiConn); // Second connection is wifi
g_ptr_array_add(dummyConns, vpnConn); // Third connection is vpn

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_))
.WillRepeatedly(::testing::Return(fakeDevices));
EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_))
.WillRepeatedly(::testing::Return("wlan0"));
EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_))
.WillRepeatedly(::testing::Return(NM_DEVICE_STATE_DISCONNECTED));

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_))
.WillRepeatedly(::testing::Return(deviceDummy));

EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_))
.WillOnce(::testing::Return());

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_))
.WillOnce(::testing::Return(reinterpret_cast<GPtrArray*>(dummyConns)));

// Setup connection IDs and types
EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_))
.WillOnce(::testing::Return("Wired connection 1")) // ethConn
.WillOnce(::testing::Return("MyWiFiNetwork")) // wifiConn - match
.WillOnce(::testing::Return("MyWiFiNetwork")) // wifiConn - for activation
.WillOnce(::testing::Return("VPN Connection")); // vpnConn
Comment on lines +2288 to +2290
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this test, the nm_connection_get_id() return sequence doesn’t align with the connection order/comment intent: the 3rd call (vpnConn in the loop) returns "MyWiFiNetwork" and the 4th call returns "VPN Connection". This can hide bugs (e.g., selecting/activating the wrong connection if the knownConnectionID is non-empty) and makes the test hard to reason about. Adjust the mocked IDs so each connection has a distinct, correctly ordered ID (ethConn="Wired connection 1", wifiConn="MyWiFiNetwork", vpnConn="VPN Connection"), and make the post-loop activation ID call return the selected connection’s ID.

Suggested change
.WillOnce(::testing::Return("MyWiFiNetwork")) // wifiConn - match
.WillOnce(::testing::Return("MyWiFiNetwork")) // wifiConn - for activation
.WillOnce(::testing::Return("VPN Connection")); // vpnConn
.WillOnce(::testing::Return("MyWiFiNetwork")) // wifiConn
.WillOnce(::testing::Return("VPN Connection")) // vpnConn
.WillOnce(::testing::Return("MyWiFiNetwork")); // selected wifiConn - for activation

Copilot uses AI. Check for mistakes.

EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_connection_type(::testing::_))
.WillOnce(::testing::Return(reinterpret_cast<const char*>("802-3-ethernet"))) // ethConn - should be skipped for wlan0
.WillOnce(::testing::Return(reinterpret_cast<const char*>("802-11-wireless"))) // wifiConn - should be selected as firstConnection
.WillOnce(::testing::Return(reinterpret_cast<const char*>("vpn"))); // vpnConn - should be skipped

EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_))
.WillRepeatedly(::testing::Return(true));

NMActiveConnection *dummyActiveConn = static_cast<NMActiveConnection*>(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL));
EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_finish(::testing::_, ::testing::_, ::testing::_))
.WillOnce(::testing::Return(dummyActiveConn));

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_))
.WillOnce(::testing::Invoke([](NMClient* client, NMConnection* connection, NMDevice* device, const char* specific_object, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) {
if (callback) {
GObject* source_object = G_OBJECT(client);
GAsyncResult* result = nullptr;
callback(source_object, result, user_data);
}
}));
Comment on lines +2304 to +2311
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test doesn’t currently assert which NMConnection* is passed to nm_client_activate_connection_async(). As written, it can still pass even if the implementation activates the wrong connection type. Tighten the expectation by matching the expected connection argument (e.g., wifiConn for wlan0) or by asserting inside the Invoke lambda that the provided connection pointer equals the expected one.

Copilot uses AI. Check for mistakes.

// Test SetInterfaceState for wlan0 which internally calls activateKnownConnection
// It should skip ethernet connection and use wifi connection as firstConnection
EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"),
_T("{\"interface\":\"wlan0\",\"enabled\":true}"), response));
EXPECT_EQ(response, _T("{\"success\":true}"));
Comment on lines +2315 to +2317
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling SetInterfaceState(enabled=true) in these tests will always incur the real sleep(1) in NetworkManagerGnomeProxy::SetInterfaceState before activateKnownConnection(). This adds at least ~1s per test case to the libnm unit test workflow. Consider restructuring the tests to exercise activateKnownConnection without going through the SetInterfaceState path, or introduce a test seam (e.g., wrapper for sleep/delay) so the delay can be bypassed in unit tests.

Suggested change
EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"),
_T("{\"interface\":\"wlan0\",\"enabled\":true}"), response));
EXPECT_EQ(response, _T("{\"success\":true}"));
#if 0
// Disabled: calling SetInterfaceState(enabled=true) incurs a real sleep(1) in
// NetworkManagerGnomeProxy::SetInterfaceState before activateKnownConnection(),
// which slows down the unit test workflow. The filtering behavior is covered by
// the ActivateKnownConnection_EthernetConnectionTypeFiltering test below.
EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"),
_T("{\"interface\":\"wlan0\",\"enabled\":true}"), response));
EXPECT_EQ(response, _T("{\"success\":true}"));
#endif

Copilot uses AI. Check for mistakes.

g_object_unref(deviceDummy);
g_object_unref(wifiConn);
g_object_unref(ethConn);
g_object_unref(vpnConn);
g_ptr_array_free(dummyConns, TRUE);
g_ptr_array_free(fakeDevices, TRUE);
}

TEST_F(NetworkManagerWifiTest, ActivateKnownConnection_EthernetConnectionTypeFiltering)
{
GPtrArray* fakeDevices = g_ptr_array_new();
NMDevice *deviceDummy = static_cast<NMDevice*>(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL));
g_ptr_array_add(fakeDevices, deviceDummy);

// Create multiple connections with different types
GPtrArray* dummyConns = g_ptr_array_new();
NMConnection *wifiConn = reinterpret_cast<NMConnection*>(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL));
NMConnection *ethConn = reinterpret_cast<NMConnection*>(g_object_new(NM_TYPE_REMOTE_CONNECTION, NULL));
g_ptr_array_add(dummyConns, wifiConn); // First connection is wifi
g_ptr_array_add(dummyConns, ethConn); // Second connection is ethernet

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_devices(::testing::_))
.WillRepeatedly(::testing::Return(fakeDevices));
EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_))
.WillRepeatedly(::testing::Return("eth0"));
EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_))
.WillRepeatedly(::testing::Return(NM_DEVICE_STATE_DISCONNECTED));

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_device_by_iface(::testing::_,::testing::_))
.WillRepeatedly(::testing::Return(deviceDummy));

EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_set_autoconnect(::testing::_,::testing::_))
.WillOnce(::testing::Return());

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_get_connections(::testing::_))
.WillOnce(::testing::Return(reinterpret_cast<GPtrArray*>(dummyConns)));

// Setup connection IDs and types
EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_id(::testing::_))
.WillOnce(::testing::Return("MyWiFiNetwork")) // ethConn - match
.WillOnce(::testing::Return("Wired connection 1")); // ethConn - for activation

EXPECT_CALL(*p_libnmWrapsImplMock, nm_connection_get_connection_type(::testing::_))
.WillOnce(::testing::Return(reinterpret_cast<const char*>("802-11-wireless"))) // wifiConn - should be skipped for eth0
.WillOnce(::testing::Return(reinterpret_cast<const char*>("802-3-ethernet"))); // ethConn - should be selected as firstConnection

EXPECT_CALL(*p_gLibWrapsImplMock, g_main_loop_is_running(::testing::_))
.WillRepeatedly(::testing::Return(true));

NMActiveConnection *dummyActiveConn = static_cast<NMActiveConnection*>(g_object_new(NM_TYPE_ACTIVE_CONNECTION, NULL));
EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_finish(::testing::_, ::testing::_, ::testing::_))
.WillOnce(::testing::Return(dummyActiveConn));

EXPECT_CALL(*p_libnmWrapsImplMock, nm_client_activate_connection_async(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_))
.WillOnce(::testing::Invoke([](NMClient* client, NMConnection* connection, NMDevice* device, const char* specific_object, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer user_data) {
if (callback) {
GObject* source_object = G_OBJECT(client);
GAsyncResult* result = nullptr;
callback(source_object, result, user_data);
}
}));
Comment on lines +2372 to +2379
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test doesn’t verify that nm_client_activate_connection_async() is invoked with the ethernet connection (ethConn). Without matching/asserting the connection argument, the test can pass even if the wrong connection is activated (especially given the current nm_connection_get_id() setup). Update the EXPECT_CALL to match ethConn (or assert inside the Invoke lambda) so the test actually enforces the intended filtering.

Copilot uses AI. Check for mistakes.

// Test SetInterfaceState for ethernet which internally calls activateKnownConnection
// It should skip wifi connection and use ethernet connection as firstConnection
EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("SetInterfaceState"),
_T("{\"interface\":\"eth0\",\"enabled\":true}"), response));
EXPECT_EQ(response, _T("{\"success\":true}"));

g_object_unref(deviceDummy);
g_object_unref(wifiConn);
g_object_unref(ethConn);
g_ptr_array_free(dummyConns, TRUE);
g_ptr_array_free(fakeDevices, TRUE);
}

TEST_F(NetworkManagerWifiTest, StopWPS)
{
EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("StopWPS"),
Expand Down