5422
5423
LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str()));
5424
5425
- // List should start empty.
5426
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
5427
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
5428
- VERIFY_ARE_EQUAL(0u, networks.size());
5425
+ // The network must not exist yet. The predefined networks are always listed.
5426
+ VERIFY_IS_FALSE(NetworkIsListed(networkName));
5427
5428
WSLCNetworkOptions options{};
5429
options.Name = networkName.c_str();
5435
auto cleanup = wil::scope_exit([&]() { LOG_IF_FAILED(m_defaultSession->DeleteNetwork(networkName.c_str())); });
5436
5437
// Verify it appears in the list with correct fields.
5440
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
5441
- VERIFY_ARE_EQUAL(1u, networks.size());
5442
- VERIFY_ARE_EQUAL(networkName, std::string(networks[0].Name));
5443
- VERIFY_ARE_EQUAL(std::string("bridge"), std::string(networks[0].Driver));
5444
- VERIFY_IS_TRUE(strlen(networks[0].Id) > 0);
5438
+ auto networks = ListNetworks();
5439
+ const auto created = std::ranges::find_if(networks, [&](const auto& network) { return network.Name == networkName; });
5440
+ VERIFY_ARE_NOT_EQUAL(networks.end(), created);
5441
+ VERIFY_ARE_EQUAL(std::string("bridge"), created->Driver);
5442
+ VERIFY_ARE_EQUAL(std::string("local"), created->Scope);
5443
+ VERIFY_IS_FALSE(created->Id.empty());
5444
+ VERIFY_IS_FALSE(created->Created.empty());
5445
+
5446
+ // The label used to track wslc managed networks is an implementation detail and must not surface.
5447
+ VERIFY_IS_FALSE(created->Labels.contains("com.microsoft.wsl.network.managed"));
5448
5449
// Duplicate name should fail.
5450
VERIFY_ARE_EQUAL(HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), m_defaultSession->CreateNetwork(&options, nullptr));
5452
cleanup.release();
5453
VERIFY_SUCCEEDED(m_defaultSession->DeleteNetwork(networkName.c_str()));
5454
5452
- // List should be empty again.
5453
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
5454
- VERIFY_ARE_EQUAL(0u, networks.size());
5455
+ VERIFY_IS_FALSE(NetworkIsListed(networkName));
5456
5457
// Delete non-existent should fail.
5458
VERIFY_ARE_EQUAL(WSLC_E_NETWORK_NOT_FOUND, m_defaultSession->DeleteNetwork(networkName.c_str()));
5459
}
5460
5461
+ std::vector<wsl::windows::common::wslc_schema::NetworkListEntry> ListNetworks(const std::vector<WSLCFilter>& Filters = {})
5462
+ {
5463
+ wil::unique_cotaskmem_ansistring output;
5464
+ VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(Filters.empty() ? nullptr : Filters.data(), static_cast<ULONG>(Filters.size()), &output));
5465
+
5466
+ return wsl::shared::FromJson<std::vector<wsl::windows::common::wslc_schema::NetworkListEntry>>(output.get());
5467
+ }
5468
+
5469
+ bool NetworkIsListed(const std::string& Name)
5470
+ {
5471
+ const auto networks = ListNetworks();
5472
+ return std::ranges::any_of(networks, [&](const auto& network) { return network.Name == Name; });
5473
+ }
5474
+
5475
void CreateNamedNetwork(const std::string& Name, const std::vector<WSLCLabel>& Labels = {})
5476
{
5477
WSLCNetworkOptions options{};
5508
const WSLCFilter* filtersPtr = filters.empty() ? nullptr : filters.data();
5509
const ULONG filtersCount = static_cast<ULONG>(filters.size());
5510
5496
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
5497
- VERIFY_ARE_EQUAL(
5498
- expected, m_defaultSession->ListNetworks(filtersPtr, filtersCount, networks.addressof(), networks.size_address<ULONG>()));
5511
+ wil::unique_cotaskmem_ansistring output;
5512
+ VERIFY_ARE_EQUAL(expected, m_defaultSession->ListNetworks(filtersPtr, filtersCount, &output));
5513
};
5514
5515
auto expectList = [&](const std::vector<std::string>& expected,
5516
const std::vector<WSLCFilter>& filters,
5517
const std::source_location& source = std::source_location::current()) {
5504
- const WSLCFilter* filtersPtr = filters.empty() ? nullptr : filters.data();
5505
- const ULONG filtersCount = static_cast<ULONG>(filters.size());
5506
-
5507
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
5508
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(filtersPtr, filtersCount, networks.addressof(), networks.size_address<ULONG>()));
5509
-
5518
std::vector<std::string> names;
5511
- for (const auto& n : networks)
5519
+ for (const auto& n : ListNetworks(filters))
5520
{
5521
names.emplace_back(n.Name);
5514
- VERIFY_IS_TRUE(strlen(n.Id) > 0);
5515
- VERIFY_ARE_EQUAL(std::string("bridge"), std::string(n.Driver));
5522
+ VERIFY_IS_FALSE(n.Id.empty());
5523
+ VERIFY_ARE_EQUAL(std::string("bridge"), n.Driver);
5524
}
5525
5526
VerifyAreEqualUnordered(expected, names, source);
5544
expectList(all, {{"label", testLabelKV.c_str()}, {"driver", "bridge"}});
5545
expectList({}, {{"label", testLabelKV.c_str()}, {"driver", "nonexistent"}});
5546
5539
- // Explicit managed-label filter is idempotent with the auto-injected one.
5547
+ // Networks created by wslc carry the managed label, which can still be filtered on explicitly.
5548
expectList(all, {{"label", testLabelKV.c_str()}, {"label", managedLabel.c_str()}});
5549
5550
+ // Predefined networks are not managed by wslc but are still listed.
5551
+ {
5552
+ const auto networks = ListNetworks();
5553
+ std::vector<std::string> names;
5554
+ for (const auto& n : networks)
5555
+ {
5556
+ names.emplace_back(n.Name);
5557
+ }
5558
+
5559
+ for (const auto& predefined : {"bridge", "host", "none"})
5560
+ {
5561
+ VERIFY_ARE_NOT_EQUAL(names.end(), std::ranges::find(names, predefined));
5562
+ }
5563
+ }
5564
+
5565
// Null filter key/value is rejected.
5566
expectListFails(E_POINTER, {{nullptr, "anything"}});
5567
expectListFails(E_POINTER, {{"label", nullptr}});
5605
5606
expectPrune({a, b});
5607
5585
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
5586
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
5587
- for (const auto& n : networks)
5588
- {
5589
- VERIFY_ARE_NOT_EQUAL(a, std::string(n.Name));
5590
- VERIFY_ARE_NOT_EQUAL(b, std::string(n.Name));
5591
- }
5608
+ VERIFY_IS_FALSE(NetworkIsListed(a));
5609
+ VERIFY_IS_FALSE(NetworkIsListed(b));
5610
5611
cleanup.release();
5612
}
5741
5742
VERIFY_SUCCEEDED(m_defaultSession->CreateNetwork(&options, nullptr));
5743
5726
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
5727
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
5728
- VERIFY_ARE_EQUAL(1u, networks.size());
5729
- VERIFY_ARE_EQUAL(networkName, std::string(networks[0].Name));
5744
+ const auto networks = ListNetworks();
5745
+ VERIFY_IS_TRUE(std::ranges::any_of(networks, [&](const auto& network) { return network.Name == networkName; }));
5746
}
5747
5748
WSLC_TEST_METHOD(NetworkCreateInvalidDriverAndOptionTest)
5802
5803
VERIFY_SUCCEEDED(m_defaultSession->CreateNetwork(&options, nullptr));
5804
5789
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
5790
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
5791
- VERIFY_ARE_EQUAL(1u, networks.size());
5792
- VERIFY_ARE_EQUAL(networkName, std::string(networks[0].Name));
5793
- VERIFY_ARE_EQUAL(std::string("bridge"), std::string(networks[0].Driver));
5805
+ const auto networks = ListNetworks();
5806
+ const auto created = std::ranges::find_if(networks, [&](const auto& network) { return network.Name == networkName; });
5807
+ VERIFY_ARE_NOT_EQUAL(networks.end(), created);
5808
+ VERIFY_ARE_EQUAL(std::string("bridge"), created->Driver);
5809
}
5810
5811
WSLC_TEST_METHOD(NetworkCreateReservedNameTest)
6012
VERIFY_IS_NOT_NULL(output.get());
6013
6014
auto inspect = wsl::shared::FromJson<wsl::windows::common::wslc_schema::Network>(output.get());
6000
- VERIFY_IS_TRUE(inspect.Options.has_value());
6001
- VERIFY_IS_TRUE(inspect.Options->contains("my.abc.key"));
6002
- VERIFY_IS_TRUE(inspect.Options->contains("com.example.flag"));
6003
- VERIFY_ARE_EQUAL(std::string("mygod"), inspect.Options->at("my.abc.key"));
6004
- VERIFY_ARE_EQUAL(std::string("1"), inspect.Options->at("com.example.flag"));
6015
+ VERIFY_IS_TRUE(inspect.Options.contains("my.abc.key"));
6016
+ VERIFY_IS_TRUE(inspect.Options.contains("com.example.flag"));
6017
+ VERIFY_ARE_EQUAL(std::string("mygod"), inspect.Options.at("my.abc.key"));
6018
+ VERIFY_ARE_EQUAL(std::string("1"), inspect.Options.at("com.example.flag"));
6019
}
6020
6021
WSLC_TEST_METHOD(NetworkSessionRecoveryTest)
6038
// Reset the session (simulates session restart).
6039
ResetTestSession();
6040
6027
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
6028
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
6029
- VERIFY_ARE_EQUAL(1u, networks.size());
6030
- VERIFY_ARE_EQUAL(networkName, std::string(networks[0].Name));
6031
- VERIFY_ARE_EQUAL(std::string("bridge"), std::string(networks[0].Driver));
6032
- VERIFY_IS_TRUE(strlen(networks[0].Id) > 0);
6041
+ const auto networks = ListNetworks();
6042
+ const auto recovered = std::ranges::find_if(networks, [&](const auto& network) { return network.Name == networkName; });
6043
+ VERIFY_ARE_NOT_EQUAL(networks.end(), recovered);
6044
+ VERIFY_ARE_EQUAL(std::string("bridge"), recovered->Driver);
6045
+ VERIFY_IS_FALSE(recovered->Id.empty());
6046
6047
// Verify arbitrary driver options survive session recovery.
6048
wil::unique_cotaskmem_ansistring output;
6050
VERIFY_IS_NOT_NULL(output.get());
6051
6052
auto inspect = wsl::shared::FromJson<wsl::windows::common::wslc_schema::Network>(output.get());
6040
- VERIFY_IS_TRUE(inspect.Options.has_value());
6041
- VERIFY_IS_TRUE(inspect.Options->contains("recovery.test.key"));
6042
- VERIFY_ARE_EQUAL(std::string("preserved"), inspect.Options->at("recovery.test.key"));
6053
+ VERIFY_IS_TRUE(inspect.Options.contains("recovery.test.key"));
6054
+ VERIFY_ARE_EQUAL(std::string("preserved"), inspect.Options.at("recovery.test.key"));
6055
}
6056
6057
WSLC_TEST_METHOD(NetworkMultipleCreateListDeleteTest)
6089
optionsC.Internal = TRUE;
6090
VERIFY_SUCCEEDED(m_defaultSession->CreateNetwork(&optionsC, nullptr));
6091
6080
- wil::unique_cotaskmem_array_ptr<WSLCNetworkInformation> networks;
6081
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
6082
- VERIFY_ARE_EQUAL(3u, networks.size());
6092
+ auto listedNames = [&]() {
6093
+ std::vector<std::string> names;
6094
+ for (const auto& network : ListNetworks())
6095
+ {
6096
+ names.push_back(network.Name);
6097
+ }
6098
+
6099
+ return names;
6100
+ };
6101
+
6102
+ auto names = listedNames();
6103
+ VERIFY_ARE_NOT_EQUAL(names.end(), std::ranges::find(names, networkNameA));
6104
+ VERIFY_ARE_NOT_EQUAL(names.end(), std::ranges::find(names, networkNameB));
6105
+ VERIFY_ARE_NOT_EQUAL(names.end(), std::ranges::find(names, networkNameC));
6106
6107
VERIFY_SUCCEEDED(m_defaultSession->DeleteNetwork(networkNameB.c_str()));
6085
- VERIFY_SUCCEEDED(m_defaultSession->ListNetworks(nullptr, 0, networks.addressof(), networks.size_address<ULONG>()));
6086
- VERIFY_ARE_EQUAL(2u, networks.size());
6108
+
6109
+ names = listedNames();
6110
+ VERIFY_ARE_NOT_EQUAL(names.end(), std::ranges::find(names, networkNameA));
6111
+ VERIFY_ARE_EQUAL(names.end(), std::ranges::find(names, networkNameB));
6112
+ VERIFY_ARE_NOT_EQUAL(names.end(), std::ranges::find(names, networkNameC));
6113
}
6114
6115
WSLC_TEST_METHOD(NetworkInspectTest)