-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add unit tests for the upgrade function
- Loading branch information
1 parent
ac4c5bc
commit bb6b0f4
Showing
6 changed files
with
236 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { ExaScriptsRow } from '@exasol/extension-manager-interface'; | ||
import { describe, expect, it } from '@jest/globals'; | ||
import { AdapterScript } from './adapterScript'; | ||
import { InstalledScripts, failureResult, successResult, validateInstalledScripts, validateVersions } from './common'; | ||
|
||
function script({ schema = "schema", name = "name", inputType, resultType = "EMITS", type = "UDF", text = "", comment }: Partial<ExaScriptsRow>): ExaScriptsRow { | ||
return { schema, name, inputType, resultType, type, text, comment } | ||
} | ||
|
||
describe("common", () => { | ||
describe("validateInstalledScripts()", () => { | ||
const importPath = script({ name: "IMPORT_PATH" }) | ||
const importMetadata = script({ name: "IMPORT_METADATA" }) | ||
const importFiles = script({ name: "IMPORT_FILES" }) | ||
const exportPath = script({ name: "EXPORT_PATH" }) | ||
const exportTable = script({ name: "EXPORT_TABLE" }) | ||
it("all scripts available", () => { | ||
const result = validateInstalledScripts([importPath, importMetadata, importFiles, exportPath, exportTable]); | ||
expect(result).toStrictEqual(successResult({ | ||
importPath: new AdapterScript(importPath), | ||
importMetadata: new AdapterScript(importMetadata), | ||
importFiles: new AdapterScript(importFiles), | ||
exportPath: new AdapterScript(exportPath), | ||
exportTable: new AdapterScript(exportTable) | ||
})) | ||
}) | ||
|
||
describe("scripts missing", () => { | ||
const tests: { name: string; scripts: ExaScriptsRow[], expectedMessage: string }[] = [ | ||
{ name: "all scripts missing", scripts: [], expectedMessage: "Validation failed: Script 'IMPORT_PATH' is missing, Script 'IMPORT_METADATA' is missing, Script 'IMPORT_FILES' is missing, Script 'EXPORT_PATH' is missing, Script 'EXPORT_TABLE' is missing" }, | ||
{ name: "importPath missing", scripts: [importMetadata, importFiles, exportPath, exportTable], expectedMessage: "Validation failed: Script 'IMPORT_PATH' is missing" }, | ||
{ name: "importMetadata missing", scripts: [importPath, importFiles, exportPath, exportTable], expectedMessage: "Validation failed: Script 'IMPORT_METADATA' is missing" }, | ||
{ name: "importFiles missing", scripts: [importPath, importMetadata, exportPath, exportTable], expectedMessage: "Validation failed: Script 'IMPORT_FILES' is missing" }, | ||
{ name: "exportPath missing", scripts: [importPath, importMetadata, importFiles, exportTable], expectedMessage: "Validation failed: Script 'EXPORT_PATH' is missing" }, | ||
{ name: "exportTable missing", scripts: [importPath, importMetadata, importFiles, exportPath], expectedMessage: "Validation failed: Script 'EXPORT_TABLE' is missing" }, | ||
] | ||
tests.forEach(test => it(test.name, () => { | ||
expect(validateInstalledScripts(test.scripts)).toStrictEqual(failureResult(test.expectedMessage)) | ||
})); | ||
}) | ||
|
||
function adapterScript(version: string | undefined): AdapterScript { | ||
return new AdapterScript(script({ text: `%jar /buckets/bfsdefault/default/exasol-cloud-storage-extension-${version ?? 'unknown-version'}.jar;` })) | ||
} | ||
|
||
function scriptVersions(importPathVersion: string | undefined, | ||
importMetadataVersion: string | undefined, importFilesVersion: string | undefined, | ||
exportPathVersion: string | undefined, exportTableVersion: string | undefined): InstalledScripts { | ||
return { | ||
importPath: adapterScript(importPathVersion), | ||
importMetadata: adapterScript(importMetadataVersion), | ||
importFiles: adapterScript(importFilesVersion), | ||
exportPath: adapterScript(exportPathVersion), | ||
exportTable: adapterScript(exportTableVersion) | ||
} | ||
} | ||
|
||
describe("validateVersions()", () => { | ||
const version = "1.2.3" | ||
it("all scripts have same version", () => { | ||
expect(validateVersions(scriptVersions(version, version, version, version, version))).toStrictEqual(successResult(version)) | ||
}) | ||
describe("not all scripts have same version", () => { | ||
const tests: { name: string; scripts: InstalledScripts, expectedMessage: string }[] = [ | ||
{ name: "unknown version", scripts: scriptVersions(undefined, undefined, undefined, undefined, undefined), expectedMessage: "Failed to get version from script 'importPath' with text '%jar /buckets/bfsdefault/default/exasol-cloud-storage-extension-unknown-version.jar;'" }, | ||
{ name: "one missing version", scripts: scriptVersions(version, version, version, version, undefined), expectedMessage: "Failed to get version from script 'exportTable' with text '%jar /buckets/bfsdefault/default/exasol-cloud-storage-extension-unknown-version.jar;'" }, | ||
{ name: "two different versions", scripts: scriptVersions(version, version, version, version, "1.2.4"), expectedMessage: "Not all scripts use the same version. Found versions: '1.2.3, 1.2.4'" }, | ||
{ name: "five different versions", scripts: scriptVersions("1.0.1", "1.0.2", "1.0.3", "1.0.4", "1.0.5"), expectedMessage: "Not all scripts use the same version. Found versions: '1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5'" }, | ||
] | ||
tests.forEach(test => it(test.name, () => { | ||
expect(validateVersions(test.scripts)).toStrictEqual(failureResult(test.expectedMessage)) | ||
})) | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { ExaScriptsRow, PreconditionFailedError } from '@exasol/extension-manager-interface'; | ||
import { describe, expect, it } from '@jest/globals'; | ||
import { createExtension } from './extension'; | ||
import { EXTENSION_DESCRIPTION } from './extension-description'; | ||
import { createMockContext, scriptWithVersion } from './test-utils'; | ||
|
||
|
||
const currentVersion = EXTENSION_DESCRIPTION.version | ||
describe("upgrade()", () => { | ||
const version = "1.2.3" | ||
const importPath = scriptWithVersion("IMPORT_PATH", version) | ||
const importMetadata = scriptWithVersion("IMPORT_METADATA", version) | ||
const importFiles = scriptWithVersion("IMPORT_FILES", version) | ||
const exportPath = scriptWithVersion("EXPORT_PATH", version) | ||
const exportTable = scriptWithVersion("EXPORT_TABLE", version) | ||
const allScripts = [importPath, importMetadata, importFiles, exportPath, exportTable] | ||
|
||
describe("validateInstalledScripts()", () => { | ||
it("success", () => { | ||
const context = createMockContext() | ||
context.mocks.simulateScripts(allScripts) | ||
expect(createExtension().upgrade(context)).toStrictEqual({ | ||
previousVersion: version, newVersion: currentVersion | ||
}) | ||
const executeCalls = context.mocks.sqlExecute.mock.calls | ||
expect(executeCalls.length).toBe(10) | ||
}) | ||
describe("failure", () => { | ||
const tests: { name: string; scripts: ExaScriptsRow[], expectedMessage: string }[] = [ | ||
{ name: "no script", scripts: [], expectedMessage: "Not all required scripts are installed: Validation failed: Script 'IMPORT_PATH' is missing, Script 'IMPORT_METADATA' is missing, Script 'IMPORT_FILES' is missing, Script 'EXPORT_PATH' is missing, Script 'EXPORT_TABLE' is missing" }, | ||
{ name: "one missing script", scripts: [importPath, importMetadata, importFiles, exportPath], expectedMessage: "Not all required scripts are installed: Validation failed: Script 'EXPORT_TABLE' is missing" }, | ||
{ name: "inconsistent versions", scripts: [importPath, importMetadata, importFiles, exportPath, scriptWithVersion("EXPORT_TABLE", "1.2.4")], expectedMessage: "Installed script use inconsistent versions: Not all scripts use the same version. Found versions: '1.2.3, 1.2.4'" }, | ||
{ | ||
name: "version already up-to-date", scripts: [ | ||
scriptWithVersion("IMPORT_PATH", currentVersion), scriptWithVersion("IMPORT_METADATA", currentVersion), | ||
scriptWithVersion("IMPORT_FILES", currentVersion), scriptWithVersion("EXPORT_PATH", currentVersion), scriptWithVersion("EXPORT_TABLE", currentVersion) | ||
], | ||
expectedMessage: "Current version 2.7.3 already installed" | ||
}, | ||
] | ||
tests.forEach(test => it(test.name, () => { | ||
const context = createMockContext() | ||
context.mocks.simulateScripts(test.scripts) | ||
expect(() => createExtension().upgrade(context)).toThrowError(new PreconditionFailedError(test.expectedMessage)) | ||
const executeCalls = context.mocks.sqlExecute.mock.calls | ||
expect(executeCalls.length).toBe(0) | ||
})) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,33 @@ | ||
import { | ||
PreconditionFailedError, | ||
UpgradeResult | ||
} from "@exasol/extension-manager-interface"; | ||
import { ExtendedContext, ExtensionInfo } from "./common"; | ||
import { ExtendedContext, ExtensionInfo, SCRIPTS, validateInstalledScripts, validateVersions } from "./common"; | ||
import { installExtension } from "./install"; | ||
|
||
|
||
function notEmpty<TValue>(value: TValue | null | undefined): value is TValue { | ||
return value !== null && value !== undefined; | ||
} | ||
|
||
export function upgrade(context: ExtendedContext, extensionInfo: ExtensionInfo): UpgradeResult { | ||
const previousVersion = "getAdapterVersion(extensionInfo, scripts)" | ||
|
||
const scriptList = Object.entries(SCRIPTS).map(([_key, value]) => value.name) | ||
.map(scriptName => context.metadata.getScriptByName(scriptName)) | ||
.filter(notEmpty); | ||
|
||
const installedScripts = validateInstalledScripts(scriptList) | ||
if (installedScripts.type === "failure") { | ||
throw new PreconditionFailedError(`Not all required scripts are installed: ${installedScripts.message}`) | ||
} | ||
const previousVersion = validateVersions(installedScripts.result) | ||
if (previousVersion.type === "failure") { | ||
throw new PreconditionFailedError(`Installed script use inconsistent versions: ${previousVersion.message}`) | ||
} | ||
const newVersion = extensionInfo.version | ||
if (previousVersion.result === newVersion) { | ||
throw new PreconditionFailedError(`Current version ${newVersion} already installed`) | ||
} | ||
installExtension(context, extensionInfo, newVersion) | ||
return { previousVersion, newVersion }; | ||
return { previousVersion: previousVersion.result, newVersion }; | ||
} |