Skip to content

Commit

Permalink
Add unit tests to test registry loading (on Windows only obv).
Browse files Browse the repository at this point in the history
Signed-off-by: Eric Promislow <[email protected]>
  • Loading branch information
ericpromislow committed Mar 23, 2023
1 parent 871f21e commit 1691e41
Show file tree
Hide file tree
Showing 2 changed files with 301 additions and 6 deletions.
293 changes: 293 additions & 0 deletions pkg/rancher-desktop/main/__tests__/deploymentProfiles.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
/* eslint object-curly-newline: ["error", {"consistent": true}] */

import fs from 'fs';
import os from 'os';
import path from 'path';

import nativeReg from 'native-reg';

import * as settings from '@pkg/config/settings';
import { defaultsHiveName, lockedHiveName, readDeploymentProfiles } from '@pkg/main/deploymentProfiles';
import { spawnFile } from '@pkg/utils/childProcess';
import Logging from '@pkg/utils/logging';
import { RecursivePartial } from '@pkg/utils/typeUtils';

const console = Logging.deploymentProfile;

const REGISTRY_PATH_PROFILE = ['SOFTWARE', 'Rancher Desktop', 'Profile'];

const describeWindows = process.platform === 'win32' ? describe : describe.skip;

let testDir = '';
let regFilePath = '';

if (Math.random() < 0.00001) {
console.log('stuff');
}

async function installInRegistry(regFileContents: string) {
await fs.promises.writeFile(regFilePath, regFileContents, { encoding: 'ucs-2' });
const { stdout, stderr } = await spawnFile('reg', ['/import', regFilePath]);

expect({ stdout, stderr }).toEqual({ stdout: '', stderr: '' });
}

// Just use the system registry file to prevent the user profile from being loaded.
// The interesting tests will happen in the user profile.

// We *could* write a routine that converts json to reg files, but that's not the point of this test.
// Better to just hard-wire a few regfiles here.

const defaultsSystemRegFile = `
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop\\Profile]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\containerEngine]
"name"="magoo"
`;

const lockedSystemRegFile = `
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop\\Profile]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\containerEngine]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rancher Desktop\\Profile\\Locked\\containerEngine\\allowedImages]
"enabled"=dword:00000001
`;

const defaultsUserRegFile = `
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\application]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\application]
"Debug"=dword:1
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\application\\Telemetry]
"ENABLED"=dword:1
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\CONTAINERENGINE]
"name"="moby"
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\containerEngine\\allowedImages]
"patterns"=hex(7):65,64,6d,6f,6e,74,6f,6e,00,63,61,6c,67,61,72,79,00,72,65,64,20,64,65,65,72,00,62,61,73,73,61,6e,6f,00,00
"enabled"=dword:00000000
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\wsl
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\wsl\\integrations
"kingston"=dword:0
"napanee"=dword:0
"yarker"=dword:1
"weed"=dword:1
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\kubernetes
"version"="867-5309"
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\diagnostics
"showmuted"=dword:1
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\diagnostics\\mutedChecks
"montreal"=dword:1
"riviere du loup"=dword:0
"magog"=dword:0
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Defaults\\extensions
"bellingham"=dword:1
"seattle"=dword:1
"olympia"=dword:0
"winthrop"=dword:1
`;

const lockedUserRegFile = `
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Locked]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Locked\\containerEngine]
[HKEY_CURRENT_USER\\SOFTWARE\\Rancher Desktop\\Profile\\Locked\\containerEngine\\allowedImages]
"enabled"=dword:00000000
"patterns"=hex(7):62,00,75,00,73,00,79,00,62,00,6f,00,78,00,00,00,6e,00,67,00,69,00,6e,00,78,00,00,00,00,00
`;

describeWindows('windows deployment profiles', () => {
beforeEach(async() => {
for (const keyName of ['HKLM', 'HKCU'] as const) {
const key = nativeReg[keyName];

for (const subkey of [defaultsHiveName, lockedHiveName]) {
nativeReg.deleteTree(key, path.join(...(REGISTRY_PATH_PROFILE.concat(subkey))));
}
}
testDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'rdtest-'));
regFilePath = path.join(testDir, 'import.reg');
});
describe('profile', () => {
describe('defaults', () => {
describe('happy paths', () => {
const defaultSystemProfile: RecursivePartial<settings.Settings> = {
containerEngine: { name: 'magoo' as settings.ContainerEngine },
};
const lockedSystemProfile: RecursivePartial<settings.Settings> = {
containerEngine: {
allowedImages: {
enabled: true,
},
},
};
const defaultUserProfile: RecursivePartial<settings.Settings> = {
application: {
debug: true,
telemetry: { enabled: false },
},
containerEngine: {
allowedImages: {
enabled: true,
patterns: ['edmonton', 'calgary', 'red deer', 'bassano'],
},
name: settings.ContainerEngine.MOBY,
},
WSL: { integrations: { kingston: false, napanee: false, yarker: true, weed: true } },
kubernetes: {
version: '867-5309',
},
diagnostics: {
showMuted: true,
mutedChecks: { montreal: true, 'riviere du loup': false, magog: false },
},
extensions: { bellingham: true, seattle: true, olympia: false, winthrop: true },
};
const lockedUserProfile = {
containerEngine: {
allowedImages: {
enabled: true,
patterns: ['edmonton', 'calgary', 'red deer', 'bassano'],
},
},
};

describe('system deployment , defaults only', () => {
beforeEach(async() => {
await installInRegistry(defaultsSystemRegFile);
});
it('loads the system profile', () => {
const profile = readDeploymentProfiles();

expect(profile.locked).toMatchObject({});
expect(profile.defaults).toMatchObject(defaultSystemProfile);
});
});

describe('system deployment, defaults and locked', () => {
beforeEach(async() => {
await installInRegistry(defaultsSystemRegFile);
await installInRegistry(lockedSystemRegFile);
});
it('loads both system profiles', () => {
const profile = readDeploymentProfiles();

expect(profile.locked).toMatchObject(lockedSystemProfile);
expect(profile.defaults).toMatchObject(defaultSystemProfile);
});
});

describe('system deployment, defaults and locked, and user defaults', () => {
beforeEach(async() => {
await installInRegistry(defaultsSystemRegFile);
await installInRegistry(lockedSystemRegFile);
await installInRegistry(defaultsUserRegFile);
});
it('loads only both system profiles', () => {
const profile = readDeploymentProfiles();

expect(profile.locked).toMatchObject(lockedSystemProfile);
expect(profile.defaults).toMatchObject(defaultSystemProfile);
});
});

describe('system deployment, defaults and locked, and user locked', () => {
beforeEach(async() => {
await installInRegistry(defaultsSystemRegFile);
await installInRegistry(lockedSystemRegFile);
await installInRegistry(lockedUserRegFile);
});
it('loads only both system profiles', () => {
const profile = readDeploymentProfiles();

expect(profile.locked).toMatchObject(lockedSystemProfile);
expect(profile.defaults).toMatchObject(defaultSystemProfile);
});
});

describe('system deployment defaults only, and both user profiles', () => {
beforeEach(async() => {
await installInRegistry(defaultsSystemRegFile);
await installInRegistry(defaultsUserRegFile);
await installInRegistry(lockedUserRegFile);
});
it('loads only the system defaults profiles', () => {
const profile = readDeploymentProfiles();

expect(profile.locked).toMatchObject({});
expect(profile.defaults).toMatchObject(defaultSystemProfile);
});
});

describe('system deployment locked only, and both user profiles', () => {
beforeEach(async() => {
await installInRegistry(lockedSystemRegFile);
await installInRegistry(defaultsUserRegFile);
await installInRegistry(lockedUserRegFile);
});
it('loads only the system locked profiles', () => {
const profile = readDeploymentProfiles();

expect(profile.defaults).toMatchObject({});
expect(profile.locked).toMatchObject(lockedSystemProfile);
});
});

describe('no system profiles, no user profiles', () => {
it('loads nothing', () => {
const profile = readDeploymentProfiles();

expect(profile.defaults).toMatchObject({});
expect(profile.locked).toMatchObject({});
});
});

describe('no system profiles, both user profiles', () => {
it('loads both profiles', () => {
const profile = readDeploymentProfiles();

expect(profile.defaults).toMatchObject(defaultUserProfile);
expect(profile.locked).toMatchObject(lockedUserProfile);
});
});
});
});
});
});
14 changes: 8 additions & 6 deletions pkg/rancher-desktop/main/deploymentProfiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const console = Logging.deploymentProfile;

const REGISTRY_PATH_PROFILE = ['SOFTWARE', 'Rancher Desktop', 'Profile'];

export const [defaultsHiveName, lockedHiveName] = process.env?.NODE_ENV === 'test' ? ['DefaultsTest', 'LockedTest'] : ['Defaults', 'Locked'];

/**
* Lockable default settings used for validating deployment profiles.
* Data values are ignored, but types are used for validation.
Expand Down Expand Up @@ -46,22 +48,22 @@ export function readDeploymentProfiles(): settings.DeploymentProfileType {

switch (os.platform()) {
case 'win32':
for (const keyName of ['HKLM', 'HKCU']) {
const key = keyName === 'HKLM' ? nativeReg.HKLM : nativeReg.HKCU;
for (const keyName of ['HKLM', 'HKCU'] as const) {
const key = nativeReg[keyName];
const registryKey = nativeReg.openKey(key, REGISTRY_PATH_PROFILE.join('\\'), nativeReg.Access.READ);

if (!registryKey) {
continue;
}
const defaultsKey = nativeReg.openKey(registryKey, 'Defaults', nativeReg.Access.READ);
const lockedKey = nativeReg.openKey(registryKey, 'Locked', nativeReg.Access.READ);
const defaultsKey = nativeReg.openKey(registryKey, defaultsHiveName, nativeReg.Access.READ);
const lockedKey = nativeReg.openKey(registryKey, lockedHiveName, nativeReg.Access.READ);

try {
if (defaultsKey) {
profiles.defaults = readRegistryUsingSchema(settings.defaultSettings, defaultsKey, [keyName, 'Defaults']) ?? {};
profiles.defaults = readRegistryUsingSchema(settings.defaultSettings, defaultsKey, [keyName, defaultsHiveName]) ?? {};
}
if (lockedKey) {
profiles.locked = readRegistryUsingSchema(settings.defaultSettings, lockedKey, [keyName, 'Locked']) ?? {};
profiles.locked = readRegistryUsingSchema(settings.defaultSettings, lockedKey, [keyName, lockedHiveName]) ?? {};
}
} catch (err) {
console.error('Error reading deployment profile: ', err);
Expand Down

0 comments on commit 1691e41

Please sign in to comment.