/* Any copyright is dedicated to the Public Domain. https://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; const { IPProtectionServerlist, PrefServerList, RemoteSettingsServerlist, IPProtectionServerlistFactory, } = ChromeUtils.importESModule( "moz-src:///toolkit/components/ipprotection/IPProtectionServerlist.sys.mjs" ); const COLLECTION_NAME = "vpn-serverlist"; const TEST_SERVER_1 = { hostname: "test1.example.com", port: 443, quarantined: false, protocols: [ { name: "connect", host: "test1.example.com", port: 8443, scheme: "https", }, ], }; const TEST_SERVER_2 = { hostname: "test2.example.com", port: 443, quarantined: false, protocols: [ { name: "connect", host: "test2.example.com", port: 8443, scheme: "https", }, ], }; const TEST_SERVER_QUARANTINED = { hostname: "quarantined.example.com", port: 443, quarantined: true, protocols: [ { name: "connect", host: "quarantined.example.com", port: 8443, scheme: "https", }, ], }; const TEST_US_CITY = { name: "Test City", code: "TC", servers: [TEST_SERVER_1, TEST_SERVER_2], }; const TEST_COUNTRIES = [ { name: "United States", code: "US", cities: [TEST_US_CITY], }, { name: "Canada", code: "CA", cities: [ { name: "Test City 2", code: "TC2", servers: [TEST_SERVER_1], }, ], }, ]; const client = RemoteSettings(COLLECTION_NAME); add_setup(async function () { do_get_profile(); await client.db.clear(); for (const country of TEST_COUNTRIES) { await client.db.create(country); } await client.db.importChanges({}, Date.now()); await IPProtectionServerlist.maybeFetchList(); await IPProtectionServerlist.initOnStartupCompleted(); Assert.ok(IPProtectionServerlist instanceof RemoteSettingsServerlist); }); add_task(async function test_getDefaultLocation() { const { country, city } = IPProtectionServerlist.getDefaultLocation(); Assert.equal(country.code, "US", "The default country should be US"); Assert.deepEqual(city, TEST_US_CITY, "The default city should be returned"); }); add_task(async function test_selectServer() { // Test with a city with multiple non-quarantined servers let selected = IPProtectionServerlist.selectServer(TEST_US_CITY); Assert.ok( [TEST_SERVER_1, TEST_SERVER_2].some(s => s.hostname === selected.hostname), "A valid server should be selected" ); // Test with a city with one server const cityWithOneServer = { name: "One Server City", code: "OSC", servers: [TEST_SERVER_1], }; selected = IPProtectionServerlist.selectServer(cityWithOneServer); Assert.deepEqual( selected, TEST_SERVER_1, "The single server should be selected" ); // Test with a city with a mix of quarantined and non-quarantined servers const cityWithMixedServers = { name: "Mixed Servers City", code: "MSC", servers: [TEST_SERVER_1, TEST_SERVER_QUARANTINED], }; selected = IPProtectionServerlist.selectServer(cityWithMixedServers); Assert.deepEqual( selected, TEST_SERVER_1, "The non-quarantined server should be selected" ); // Test with a city with only quarantined servers const cityWithQuarantinedServers = { name: "Quarantined City", code: "QC", servers: [TEST_SERVER_QUARANTINED], }; selected = IPProtectionServerlist.selectServer(cityWithQuarantinedServers); Assert.equal(selected, null, "No server should be selected"); // Test with a city with no servers const cityWithNoServers = { name: "No Server City", code: "NSC", servers: [], }; selected = IPProtectionServerlist.selectServer(cityWithNoServers); Assert.equal(selected, null, "No server should be selected"); }); add_task(async function test_syncRespected() { let { country, city } = IPProtectionServerlist.getDefaultLocation(); Assert.equal(country.code, "US", "The default country should be US"); Assert.deepEqual(city, TEST_US_CITY, "The correct city should be returned"); // Now, update the server list to remove the US entry const updated_server = { ...TEST_SERVER_1, hostname: "updated.example.com", }; const updated_city = { ...TEST_US_CITY, servers: [updated_server], }; const updated_country = { ...TEST_COUNTRIES[0], cities: [updated_city], }; await client.db.clear(); await client.db.create(updated_country); await client.db.importChanges({}, Date.now()); await client.emit("sync", { data: {} }); await IPProtectionServerlist.maybeFetchList(); ({ country, city } = IPProtectionServerlist.getDefaultLocation()); Assert.equal(country.code, "US", "The default country should be US"); Assert.deepEqual(city, updated_city, "The updated city should be returned"); }); add_task(async function test_PrefServerList() { registerCleanupFunction(() => { Services.prefs.clearUserPref(PrefServerList.PREF_NAME); }); Services.prefs.setCharPref( PrefServerList.PREF_NAME, JSON.stringify(TEST_COUNTRIES) ); Assert.equal( PrefServerList.hasPrefValue, true, "PrefServerList should have a pref value set." ); Assert.deepEqual( PrefServerList.prefValue, TEST_COUNTRIES, "PrefServerList's pref value should match the set value." ); const serverList = new PrefServerList(); await serverList.maybeFetchList(); const { country, city } = serverList.getDefaultLocation(); Assert.equal(country.code, "US", "The default country should be US"); Assert.deepEqual(city, TEST_US_CITY, "The default city should be returned."); }); add_task(async function test_IPProtectionServerlistFactory() { registerCleanupFunction(() => { Services.prefs.clearUserPref(PrefServerList.PREF_NAME); }); // Without the pref set, it should return RemoteSettingsServerlist Services.prefs.clearUserPref(PrefServerList.PREF_NAME); let instance = IPProtectionServerlistFactory(); Assert.ok(instance instanceof RemoteSettingsServerlist); Services.prefs.setCharPref( PrefServerList.PREF_NAME, JSON.stringify(TEST_COUNTRIES) ); // With the pref set, it should return PrefServerList Assert.ok(IPProtectionServerlistFactory() instanceof PrefServerList); });