Skip to content

Commit 73e7465

Browse files
Copilotlive1206
andcommitted
Add test to demonstrate resolveArmResources API bug with multiple singletons
Co-authored-by: live1206 <[email protected]>
1 parent 4ed8a25 commit 73e7465

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
/**
5+
* This test file demonstrates a bug in the resolveArmResources API from
6+
* @azure-tools/typespec-azure-resource-manager.
7+
*
8+
* Bug Description:
9+
* When multiple singleton resources are defined with different @singleton keys
10+
* (e.g., Employee with default key and CurrentEmployee with "current" key),
11+
* the resolveArmResources API does not properly distinguish between them.
12+
* All resolved resources point to the same model type instead of their respective types.
13+
*
14+
* This test is marked with .skip because it demonstrates a bug in an external library
15+
* that needs to be fixed before the test will pass.
16+
*/
17+
18+
import { beforeEach, describe, it } from "vitest";
19+
import {
20+
createEmitterTestHost,
21+
typeSpecCompile
22+
} from "./test-util.js";
23+
import { TestHost } from "@typespec/compiler/testing";
24+
import { resolveArmResources } from "@azure-tools/typespec-azure-resource-manager";
25+
import { strictEqual, ok } from "assert";
26+
27+
/**
28+
* Shared TypeSpec schema for multiple singleton resources test.
29+
* Defines two singleton resources with different @singleton keys.
30+
*/
31+
const multipleSingletonsSchema = `
32+
/** Employee properties */
33+
model EmployeeProperties {
34+
/** Age of employee */
35+
age?: int32;
36+
}
37+
38+
/** An Employee singleton resource with default key */
39+
@singleton
40+
model Employee is TrackedResource<EmployeeProperties> {
41+
...ResourceNameParameter<Employee>;
42+
}
43+
44+
/** A CurrentEmployee singleton resource with "current" key */
45+
@singleton("current")
46+
model CurrentEmployee is TrackedResource<EmployeeProperties> {
47+
...ResourceNameParameter<CurrentEmployee>;
48+
}
49+
50+
interface Operations extends Azure.ResourceManager.Operations {}
51+
52+
@armResourceOperations
53+
interface Employees {
54+
get is ArmResourceRead<Employee>;
55+
createOrUpdate is ArmResourceCreateOrReplaceAsync<Employee>;
56+
}
57+
58+
@armResourceOperations
59+
interface CurrentEmployees {
60+
get is ArmResourceRead<CurrentEmployee>;
61+
createOrUpdate is ArmResourceCreateOrReplaceAsync<CurrentEmployee>;
62+
}
63+
`;
64+
65+
describe("resolveArmResources API Bug Demonstration", () => {
66+
let runner: TestHost;
67+
beforeEach(async () => {
68+
runner = await createEmitterTestHost();
69+
});
70+
71+
/**
72+
* This test demonstrates that resolveArmResources does not correctly return
73+
* multiple singleton resources with different @singleton keys.
74+
*
75+
* Expected behavior: The API should return both Employee and CurrentEmployee
76+
* as separate resources with their respective model types.
77+
*
78+
* Actual behavior: All resolved resources have type.name === "Employee",
79+
* meaning CurrentEmployee is never properly identified.
80+
*/
81+
it.skip("should return distinct resources for multiple singletons with different keys", async () => {
82+
const program = await typeSpecCompile(multipleSingletonsSchema, runner);
83+
84+
// Use resolveArmResources API to get all resolved ARM resources
85+
const provider = resolveArmResources(program);
86+
const resolvedResources = provider.resources ?? [];
87+
88+
// Check that we have resources returned
89+
ok(resolvedResources.length > 0, "Should have at least one resolved resource");
90+
91+
// Find resources by their model type name
92+
const employeeResources = resolvedResources.filter(
93+
(r) => r.type.name === "Employee"
94+
);
95+
const currentEmployeeResources = resolvedResources.filter(
96+
(r) => r.type.name === "CurrentEmployee"
97+
);
98+
99+
// BUG: This assertion fails because resolveArmResources returns all resources
100+
// with type.name === "Employee" instead of distinguishing CurrentEmployee
101+
ok(
102+
currentEmployeeResources.length > 0,
103+
"Should have at least one CurrentEmployee resource - BUG: resolveArmResources does not return CurrentEmployee"
104+
);
105+
106+
// Verify that Employee resources are returned correctly
107+
ok(
108+
employeeResources.length > 0,
109+
"Should have at least one Employee resource"
110+
);
111+
112+
// Verify that the total count is correct (should be 2 distinct resources for CRUD operations)
113+
// Note: The API may return multiple entries per resource for different operation paths
114+
const uniqueResourceTypes = new Set(resolvedResources.map((r) => r.type.name));
115+
strictEqual(
116+
uniqueResourceTypes.size,
117+
2,
118+
"Should have exactly 2 unique resource types (Employee and CurrentEmployee)"
119+
);
120+
});
121+
122+
/**
123+
* This test shows the current (buggy) behavior of resolveArmResources
124+
* where all resources point to the same model type.
125+
*/
126+
it("demonstrates current buggy behavior - all resources have same type", async () => {
127+
const program = await typeSpecCompile(multipleSingletonsSchema, runner);
128+
129+
// Use resolveArmResources API to get all resolved ARM resources
130+
const provider = resolveArmResources(program);
131+
const resolvedResources = provider.resources ?? [];
132+
133+
// BUG: All resolved resources have type.name === "Employee"
134+
// CurrentEmployee is never returned despite being defined
135+
const allResourceTypeNames = resolvedResources.map((r) => r.type.name);
136+
const uniqueResourceTypes = new Set(allResourceTypeNames);
137+
138+
// This assertion passes but demonstrates the bug:
139+
// We expect 2 unique types but only get 1
140+
strictEqual(
141+
uniqueResourceTypes.size,
142+
1,
143+
"BUG: resolveArmResources only returns Employee type, missing CurrentEmployee"
144+
);
145+
146+
// All resources point to Employee
147+
ok(
148+
allResourceTypeNames.every((name) => name === "Employee"),
149+
"BUG: All resolved resources have type Employee"
150+
);
151+
152+
// CurrentEmployee is never returned
153+
const hasCurrentEmployee = allResourceTypeNames.some(
154+
(name) => name === "CurrentEmployee"
155+
);
156+
strictEqual(
157+
hasCurrentEmployee,
158+
false,
159+
"BUG: CurrentEmployee is never returned by resolveArmResources"
160+
);
161+
});
162+
});

0 commit comments

Comments
 (0)