Skip to content

Commit 1d55758

Browse files
internal(Load Zones): Generate code for load zones (#526)
1 parent af658a7 commit 1d55758

File tree

13 files changed

+120
-35
lines changed

13 files changed

+120
-35
lines changed

src/codegen/codegen.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ describe('Code generation', () => {
9595
cloud: {
9696
loadZones: {
9797
distribution: 'even',
98-
loadZones: [],
98+
zones: [],
9999
},
100100
},
101101
},
@@ -134,7 +134,7 @@ describe('Code generation', () => {
134134
cloud: {
135135
loadZones: {
136136
distribution: 'even',
137-
loadZones: [],
137+
zones: [],
138138
},
139139
},
140140
},

src/codegen/options.test.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { describe, expect, it } from 'vitest'
22

3-
import { generateOptions, generateThresholds } from './options'
3+
import {
4+
generateCloudOptions,
5+
generateOptions,
6+
generateThresholds,
7+
} from './options'
48
import {
59
LoadProfileExecutorOptions,
10+
LoadZoneData,
611
TestOptions,
712
Threshold,
813
} from '@/types/testOptions'
914
import { createThreshold } from '@/test/factories/threshold'
15+
import { createLoadZone } from '@/test/factories/loadZones'
1016

1117
describe('Code generation - options', () => {
1218
it('should generate load profile for shared-iterations executor', () => {
@@ -118,3 +124,41 @@ describe('Code generation - thresholds', () => {
118124
expect(generateThresholds(thresholds)).toEqual(expectedResult)
119125
})
120126
})
127+
128+
describe('Code generation - cloud options', () => {
129+
it('should generate load zones correctly', () => {
130+
const loadZones: LoadZoneData = {
131+
distribution: 'even',
132+
zones: [
133+
createLoadZone({ loadZone: 'amazon:us:columbus', percent: 50 }),
134+
createLoadZone({ loadZone: 'amazon:br:sao paulo', percent: 50 }),
135+
],
136+
}
137+
138+
const expectedResult = {
139+
cloud: {
140+
distribution: {
141+
"'amazon:us:columbus'": {
142+
loadZone: 'amazon:us:columbus',
143+
percent: 50,
144+
},
145+
"'amazon:br:sao paulo'": {
146+
loadZone: 'amazon:br:sao paulo',
147+
percent: 50,
148+
},
149+
},
150+
},
151+
}
152+
153+
expect(generateCloudOptions({ loadZones })).toEqual(expectedResult)
154+
})
155+
156+
it('should not generate cloud object when load zones are not selected', () => {
157+
const loadZones: LoadZoneData = {
158+
distribution: 'even',
159+
zones: [],
160+
}
161+
162+
expect(generateCloudOptions({ loadZones })).toEqual({})
163+
})
164+
})

src/codegen/options.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import { TestOptions, Threshold } from '@/types/testOptions'
1+
import { LoadZoneData, TestOptions, Threshold } from '@/types/testOptions'
22
import { stringify } from './codegen.utils'
33
import { omit } from 'lodash-es'
44

55
export function generateOptions({
66
loadProfile,
77
thresholds,
8+
cloud,
89
}: TestOptions): string {
910
const options = omit(loadProfile, ['executor'])
1011
const data = {
1112
...options,
13+
...(cloud && generateCloudOptions(cloud)),
1214
...(thresholds.length > 0 && {
1315
thresholds: generateThresholds(thresholds),
1416
}),
@@ -42,3 +44,23 @@ export function generateThresholds(thresholds: Threshold[]) {
4244

4345
return result
4446
}
47+
48+
export function generateCloudOptions({ loadZones }: TestOptions['cloud']) {
49+
if (loadZones.zones.length === 0) return {}
50+
51+
return {
52+
cloud: {
53+
distribution: generateLoadZones(loadZones.zones),
54+
},
55+
}
56+
}
57+
58+
export function generateLoadZones(loadZones: LoadZoneData['zones']) {
59+
const result: Record<string, { loadZone: string; percent: number }> = {}
60+
61+
loadZones.forEach(({ loadZone, percent }) => {
62+
result[`'${loadZone}'`] = { loadZone, percent }
63+
})
64+
65+
return result
66+
}

src/schemas/generator/v0/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function migrate(generator: GeneratorSchema): v1.GeneratorSchema {
2626
...generator.options,
2727
thresholds: [],
2828
cloud: {
29-
loadZones: { distribution: 'even', loadZones: [] },
29+
loadZones: { distribution: 'even', zones: [] },
3030
},
3131
},
3232
testData: { ...generator.testData, files: [] },

src/schemas/generator/v1/loadZone.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,34 @@ export const AvailableLoadZonesSchema = z.enum([
2727
export const LoadZoneItemSchema = z.object({
2828
id: z.string(),
2929
loadZone: AvailableLoadZonesSchema,
30-
percent: z.number().int().min(1, { message: 'Invalid percentage' }).max(100),
30+
percent: z
31+
.number({ message: 'Invalid percentage' })
32+
.int()
33+
.min(1, { message: 'Invalid percentage' })
34+
.max(100, { message: 'Invalid percentage' }),
3135
})
3236

3337
export const LoadZoneSchema = z.object({
3438
distribution: z.enum(['even', 'manual']),
35-
loadZones: z.array(LoadZoneItemSchema).refine(
39+
zones: z.array(LoadZoneItemSchema).refine(
3640
(data) => {
3741
if (data.length === 0) {
3842
return true
3943
}
4044

41-
const totalPercentage = data.reduce(
42-
(sum, { percent }) => sum + percent,
43-
0
44-
)
45+
const totalPercentage = currentLoadZonePercentage(data)
4546
return totalPercentage === 100
4647
},
47-
{ message: 'The sum of all distribution percentages must be 100' }
48+
(data) => {
49+
const totalPercentage = currentLoadZonePercentage(data)
50+
return {
51+
message: `Total percentage must be 100, currently ${totalPercentage}`,
52+
path: ['root'],
53+
}
54+
}
4855
),
4956
})
57+
58+
function currentLoadZonePercentage(data: { percent: number }[]) {
59+
return data.reduce((sum, { percent }) => sum + percent, 0)
60+
}

src/schemas/generator/v1/testOptions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,5 @@ export const TestOptionsSchema = z.object({
7373
.object({
7474
loadZones: LoadZoneSchema,
7575
})
76-
.default({ loadZones: { distribution: 'even', loadZones: [] } }),
76+
.default({ loadZones: { distribution: 'even', zones: [] } }),
7777
})

src/store/generator/slices/testOptions/loadZones.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface Actions {
1212
export type LoadZoneStore = State & Actions
1313

1414
export const createLoadZoneSlice: ImmerStateCreator<LoadZoneStore> = (set) => ({
15-
loadZones: { distribution: 'even', loadZones: [] },
15+
loadZones: { distribution: 'even', zones: [] },
1616
setLoadZones: (loadZones: LoadZoneData) =>
1717
set((state) => {
1818
state.loadZones = loadZones

src/test/factories/generator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function createGeneratorData(
2424
cloud: {
2525
loadZones: {
2626
distribution: 'even',
27-
loadZones: [],
27+
zones: [],
2828
},
2929
},
3030
},
@@ -106,7 +106,7 @@ export function createGeneratorState(
106106

107107
loadZones: {
108108
distribution: 'even',
109-
loadZones: [],
109+
zones: [],
110110
},
111111
setLoadZones: vi.fn(),
112112

src/test/factories/loadZones.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { LoadZoneItem } from '@/types/testOptions'
2+
3+
export function createLoadZone(loadZone?: Partial<LoadZoneItem>): LoadZoneItem {
4+
return {
5+
id: crypto.randomUUID(),
6+
loadZone: 'amazon:us:columbus',
7+
percent: 50,
8+
...loadZone,
9+
}
10+
}

src/utils/generator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function createNewGeneratorFile(recordingPath = ''): GeneratorFileData {
2222
cloud: {
2323
loadZones: {
2424
distribution: 'even',
25-
loadZones: [],
25+
zones: [],
2626
},
2727
},
2828
},

0 commit comments

Comments
 (0)