Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate new validation code that fixes linked/nested templates #806

Merged
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.10.1-alpha",
"publisher": "msazurermtools",
"config": {
"ARM_LANGUAGE_SERVER_NUGET_VERSION": "3.0.0-preview.20317.6"
"ARM_LANGUAGE_SERVER_NUGET_VERSION": "3.0.0-preview.20319.5"
},
"categories": [
"Azure",
Expand Down
5 changes: 4 additions & 1 deletion test/DeploymentTemplate.CodeLenses.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ suite("DeploymentTemplate code lenses", () => {
`${topLevelParamName} with no value in param file` :
`${topLevelParamName} with value ${JSON.stringify(valueInParamFile).replace(/\r\n|\n/g, ' ')}`;
test(testName, async () => {
let a = testName;
a = a;
const dt = await parseTemplate(template);
const param = dt.topLevelScope.getParameterDefinition(topLevelParamName);
assert(!!param);
Expand Down Expand Up @@ -188,7 +190,8 @@ suite("DeploymentTemplate code lenses", () => {
const lens = lenses.find(l => l.parameterDefinition === param);
assert(!!lens, `Couldn't find a code lens for parameter ${param.nameValue.unquotedValue}`);

lens.resolve(dp);
const result = lens.resolve(dp);
assert.equal(result, true);
assert.equal(lens.command?.command, "azurerm-vscode-tools.codeLens.gotoParameterValue");
assert.deepEqual(lens.command?.arguments, [
dp.documentUri,
Expand Down
138 changes: 137 additions & 1 deletion test/LinkedTemplates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
// tslint:disable:no-unused-expression max-func-body-length promise-function-async max-line-length no-unnecessary-class
// tslint:disable:no-non-null-assertion object-literal-key-quotes variable-name no-constant-condition

import { testDiagnosticsFromFile } from "./support/diagnostics";
import { isWin32 } from "../extension.bundle";
import { testDiagnostics, testDiagnosticsFromFile } from "./support/diagnostics";

suite("Linked templates", () => {
suite("variables and parameters inside templateLink object refer to the parent's scope", () => {
Expand All @@ -18,5 +19,140 @@ suite("Linked templates", () => {
]
);
});

suite('Regress #773: Regression from 0.10.0: top-level parameters not recognized in nested template properties', () => {
test("simple", async () => {
await testDiagnosticsFromFile(
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "aadLinkedTemplate",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://foo"
}
}
}
]
},
{
parameters: {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {}
}
},
[
// Should be no errors
]);
});
test("linked-templates-scope.json", async () => {
await testDiagnosticsFromFile(
'templates/linked-templates-scope.json',
{
parameters: {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {}
}
},
[
// Should be no errors
]
);
});
});
});

suite("Error location inside linked and nested templates", async () => {
// tslint:disable-next-line: no-suspicious-comment
// TODO: For some reason, these two tests are failing consistently in the
// Windows build pipeline, but not locally or on other platforms.
if (!isWin32) {
test("Nested template wrong param type", async () => {
await testDiagnostics(
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "inner",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {
"parameter1": {
"value": 123
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"parameter1": {
"type": "string"
}
},
"resources": []
}
}
}
]
},
{
includeRange: true,
parameters: {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
}
}
},
[
"Error: Template validation failed: Template parameter JToken type is not valid. Expected 'String, Uri'. Actual 'Integer'. Please see https://aka.ms/arm-deploy/#parameter-file for usage details. (arm-template (validation)) [8,20-8,20] [The error occurred in a nested template near here] [13,39-13,39]",
"Warning: The parameter 'parameter1' is never used. (arm-template (expressions)) [22,12-22,24]"
]
);
});

test("Nested template missing properties", async () => {
await testDiagnostics(
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-10-01",
"name": "inner"
}
]
},
{
includeRange: true,
parameters: {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
}
}
},
[
"Error: Template validation failed: The deployment must have Properties property set. Please see https://aka.ms/arm-deploy for usage details. (arm-template (validation)) [4,4-4,4]",
"Warning: Missing required property \"properties\" (arm-template (schema)) [4,4-4,5]"

]
);
});
}
});
});
2 changes: 1 addition & 1 deletion test/functional/expressions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ suite("Expressions functional tests", () => {
template,
{
includeSources: [diagnosticSources.expressions],
includeRange: true
includeRange: false
},
expected);
});
Expand Down
4 changes: 2 additions & 2 deletions test/functional/validation.regression.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ suite("Validation regression tests", () => {

// tslint:disable-next-line: no-suspicious-comment
// TODO: https://github.com/microsoft/vscode-azurearmtools/issues/673
"Error: Expected a comma (','). (arm-template (expressions))",
"Error: Expected a comma (','). (arm-template (expressions)) [187,357-187,359]",

// Expected schema errors:
`Warning: Value must be one of the following types: boolean (arm-template (schema))`
"Warning: Value must be one of the following types: boolean (arm-template (schema)) [145,16-145,31]"
]
)
);
Expand Down
36 changes: 22 additions & 14 deletions test/support/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const DEBUG_BREAK_AFTER_DIAGNOSTICS_COMPLETE = false;
import * as assert from "assert";
import * as fs from 'fs';
import * as path from 'path';
import { Diagnostic, DiagnosticSeverity, Disposable, languages, TextDocument } from "vscode";
import { Diagnostic, DiagnosticSeverity, Disposable, languages, Range, TextDocument } from "vscode";
import { diagnosticsCompletePrefix, expressionsDiagnosticsSource, ExpressionType, ext, LanguageServerState, languageServerStateSource } from "../../extension.bundle";
import { DISABLE_LANGUAGE_SERVER } from "../testConstants";
import { parseParametersWithMarkers } from "./parseTemplate";
Expand Down Expand Up @@ -452,7 +452,7 @@ export async function getDiagnosticsForTemplate(
}
}

function diagnosticToString(diagnostic: Diagnostic, options: IGetDiagnosticsOptions, includeRange: boolean): string {
export function diagnosticToString(diagnostic: Diagnostic, options: IGetDiagnosticsOptions, includeRange: boolean): string {
assert(diagnostic.code === '', `Expecting empty code for all diagnostics, instead found Code="${String(diagnostic.code)}" for "${diagnostic.message}"`);

let severity: string = "";
Expand All @@ -464,26 +464,34 @@ function diagnosticToString(diagnostic: Diagnostic, options: IGetDiagnosticsOpti
default: assert.fail(`Expected severity ${diagnostic.severity}`);
}

let s = `${severity}: ${diagnostic.message} (${diagnostic.source})`;

// Do the expected messages include ranges?
if (includeRange) {
// tslint:disable-next-line: strict-boolean-expressions
if (!diagnostic.range) {
s += " []";
} else {
s += ` [${diagnostic.range.start.line},${diagnostic.range.start.character}`
+ `-${diagnostic.range.end.line},${diagnostic.range.end.character}]`;
}
let s = `${severity}: ${diagnostic.message} (${diagnostic.source})${rangeAsString(diagnostic.range)}`;
if (diagnostic.relatedInformation) {
const related = diagnostic.relatedInformation[0];
s = `${s} [${related.message}]${rangeAsString(related.location.range)}`;
}

return s;

function rangeAsString(range: Range): string {
// Do the expected messages include ranges?
if (includeRange) {
// tslint:disable-next-line: strict-boolean-expressions
if (!range) {
return "[]";
} else {
return ` [${range.start.line},${range.start.character}`
+ `-${range.end.line},${range.end.character}]`;
}
}

return "";
}
}

function compareDiagnostics(actual: Diagnostic[], expected: string[], options: ITestDiagnosticsOptions): void {
// Do the expected messages include ranges?
let expectedHasRanges = expected.length === 0 || !!expected[0].match(/[0-9]+,[0-9]+-[0-9]+,[0-9]+/);
let includeRanges = !!options.includeRange && expectedHasRanges;
let includeRanges = !!options.includeRange || expectedHasRanges;

let actualAsStrings = actual.map(d => diagnosticToString(d, options, includeRanges));

Expand Down