@uql/core 0.4.81 → 0.4.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dialect/abstractSqlDialect-spec.d.ts +49 -0
- package/dialect/abstractSqlDialect-spec.js +765 -0
- package/dialect/mysqlDialect.spec.d.ts +6 -0
- package/dialect/mysqlDialect.spec.js +33 -0
- package/dialect/postgresDialect.spec.d.ts +1 -0
- package/dialect/postgresDialect.spec.js +139 -0
- package/dialect/sqliteDialect.spec.d.ts +1 -0
- package/dialect/sqliteDialect.spec.js +12 -0
- package/entity/decorator/definition.spec.d.ts +1 -0
- package/entity/decorator/definition.spec.js +737 -0
- package/entity/decorator/relation.spec.d.ts +1 -0
- package/entity/decorator/relation.spec.js +55 -0
- package/options.spec.d.ts +1 -0
- package/options.spec.js +50 -0
- package/package.json +3 -3
- package/querier/abstractQuerier-it.d.ts +41 -0
- package/querier/abstractQuerier-it.js +410 -0
- package/querier/abstractSqlQuerier-it.d.ts +9 -0
- package/querier/abstractSqlQuerier-it.js +19 -0
- package/querier/abstractSqlQuerier-spec.d.ts +53 -0
- package/querier/abstractSqlQuerier-spec.js +609 -0
- package/querier/decorator/injectQuerier.spec.d.ts +1 -0
- package/querier/decorator/injectQuerier.spec.js +108 -0
- package/querier/decorator/transactional.spec.d.ts +1 -0
- package/querier/decorator/transactional.spec.js +241 -0
- package/repository/genericRepository.spec.d.ts +1 -0
- package/repository/genericRepository.spec.js +86 -0
- package/test/entityMock.d.ts +180 -0
- package/test/entityMock.js +451 -0
- package/test/index.d.ts +3 -0
- package/test/index.js +7 -0
- package/test/it.util.d.ts +4 -0
- package/test/it.util.js +60 -0
- package/test/spec.util.d.ts +13 -0
- package/test/spec.util.js +54 -0
- package/util/dialect.util.spec.d.ts +1 -0
- package/util/dialect.util.spec.js +23 -0
- package/util/object.util.spec.d.ts +1 -0
- package/util/object.util.spec.js +26 -0
- package/util/sql.util.spec.d.ts +1 -0
- package/util/sql.util.spec.js +164 -0
- package/util/string.util.spec.d.ts +1 -0
- package/util/string.util.spec.js +26 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractSqlQuerierSpec = void 0;
|
|
4
|
+
const raw_1 = require("@uql/core/util/raw");
|
|
5
|
+
const test_1 = require("@uql/core/test");
|
|
6
|
+
class AbstractSqlQuerierSpec {
|
|
7
|
+
constructor(pool, idType) {
|
|
8
|
+
this.pool = pool;
|
|
9
|
+
this.idType = idType;
|
|
10
|
+
}
|
|
11
|
+
async beforeAll() {
|
|
12
|
+
this.querier = await this.pool.getQuerier();
|
|
13
|
+
await (0, test_1.dropTables)(this.querier);
|
|
14
|
+
await (0, test_1.createTables)(this.querier, this.idType);
|
|
15
|
+
await this.querier.release();
|
|
16
|
+
}
|
|
17
|
+
async beforeEach() {
|
|
18
|
+
this.querier = await this.pool.getQuerier();
|
|
19
|
+
await (0, test_1.clearTables)(this.querier);
|
|
20
|
+
jest.spyOn(this.querier, 'all');
|
|
21
|
+
jest.spyOn(this.querier, 'run');
|
|
22
|
+
}
|
|
23
|
+
async afterEach() {
|
|
24
|
+
jest.restoreAllMocks();
|
|
25
|
+
await this.querier.release();
|
|
26
|
+
}
|
|
27
|
+
async afterAll() {
|
|
28
|
+
await this.pool.end();
|
|
29
|
+
}
|
|
30
|
+
async shouldFindOneById() {
|
|
31
|
+
await this.querier.findOneById(test_1.User, 1);
|
|
32
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id`, `companyId`, `creatorId`, `createdAt`, `updatedAt`, `name`, `email`, `password` FROM `User` WHERE `id` = 1 LIMIT 1');
|
|
33
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
34
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
35
|
+
}
|
|
36
|
+
async shouldFindOne() {
|
|
37
|
+
await this.querier.findOne(test_1.User, { $project: ['id', 'name'], $filter: { companyId: 123 } });
|
|
38
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id`, `name` FROM `User` WHERE `companyId` = 123 LIMIT 1');
|
|
39
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
40
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
41
|
+
}
|
|
42
|
+
async shouldFindOneAndProjectOneToMany() {
|
|
43
|
+
await this.querier.insertMany(test_1.InventoryAdjustment, [
|
|
44
|
+
{
|
|
45
|
+
id: 123,
|
|
46
|
+
createdAt: 1,
|
|
47
|
+
},
|
|
48
|
+
{ id: 456, createdAt: 1 },
|
|
49
|
+
]);
|
|
50
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `InventoryAdjustment` (`id`, `createdAt`) VALUES (123, 1), (456, 1)');
|
|
51
|
+
await this.querier.findMany(test_1.InventoryAdjustment, {
|
|
52
|
+
$project: ['id', 'itemAdjustments'],
|
|
53
|
+
$filter: { createdAt: 1 },
|
|
54
|
+
});
|
|
55
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `InventoryAdjustment`.`id` FROM `InventoryAdjustment` WHERE `InventoryAdjustment`.`createdAt` = 1');
|
|
56
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id`, `companyId`, `creatorId`, `createdAt`, `updatedAt`, `itemId`, `number`, `buyPrice`, `storehouseId`' +
|
|
57
|
+
', `inventoryAdjustmentId` FROM `ItemAdjustment` WHERE `inventoryAdjustmentId` IN (123, 456)');
|
|
58
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
59
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
60
|
+
}
|
|
61
|
+
async shouldFindAndProjectRaw() {
|
|
62
|
+
await this.querier.findMany(test_1.InventoryAdjustment, {
|
|
63
|
+
$project: {
|
|
64
|
+
creator: ['id', 'name'],
|
|
65
|
+
itemAdjustments: {
|
|
66
|
+
$project: {
|
|
67
|
+
item: {
|
|
68
|
+
$project: {
|
|
69
|
+
companyId: true,
|
|
70
|
+
total: (0, raw_1.raw)(({ escapedPrefix, dialect }) => `SUM(${escapedPrefix}${dialect.escapeId('salePrice')})`),
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
$sort: { createdAt: -1 },
|
|
75
|
+
$limit: 100,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
$filter: {
|
|
79
|
+
companyId: 1,
|
|
80
|
+
},
|
|
81
|
+
$sort: { creator: { name: 'asc' } },
|
|
82
|
+
});
|
|
83
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `InventoryAdjustment`.`id`, `creator`.`id` `creator.id`, `creator`.`name` `creator.name`' +
|
|
84
|
+
' FROM `InventoryAdjustment` LEFT JOIN `User` `creator` ON `creator`.`id` = `InventoryAdjustment`.`creatorId`' +
|
|
85
|
+
' WHERE `InventoryAdjustment`.`companyId` = 1 ORDER BY `creator`.`name`');
|
|
86
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `ItemAdjustment`.`id`, `ItemAdjustment`.`inventoryAdjustmentId`' +
|
|
87
|
+
', `item`.`id` `item.id`, `item`.`companyId` `item.companyId`, SUM(`item`.`salePrice`) `item.total`' +
|
|
88
|
+
' FROM `ItemAdjustment` LEFT JOIN `Item` `item` ON `item`.`id` = `ItemAdjustment`.`itemId`' +
|
|
89
|
+
' WHERE `ItemAdjustment`.`inventoryAdjustmentId` IN ()' +
|
|
90
|
+
' ORDER BY `ItemAdjustment`.`createdAt`' +
|
|
91
|
+
' DESC LIMIT 100');
|
|
92
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
93
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
94
|
+
}
|
|
95
|
+
async shouldVirtualField() {
|
|
96
|
+
await this.querier.findMany(test_1.Item, {
|
|
97
|
+
$project: {
|
|
98
|
+
id: 1,
|
|
99
|
+
},
|
|
100
|
+
$filter: {
|
|
101
|
+
tagsCount: { $gte: 10 },
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
expect(this.querier.all).toBeCalledWith('SELECT `id` FROM `Item` WHERE (SELECT COUNT(*) `count` FROM `ItemTag` WHERE `ItemTag`.`itemId` = `id`) >= 10');
|
|
105
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
106
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
107
|
+
jest.clearAllMocks();
|
|
108
|
+
await this.querier.findMany(test_1.Item, {
|
|
109
|
+
$project: {
|
|
110
|
+
id: 1,
|
|
111
|
+
name: 1,
|
|
112
|
+
code: 1,
|
|
113
|
+
tagsCount: 1,
|
|
114
|
+
measureUnit: {
|
|
115
|
+
$project: { id: 1, name: 1, categoryId: 1, category: ['name'] },
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
$limit: 100,
|
|
119
|
+
});
|
|
120
|
+
expect(this.querier.all).toBeCalledWith('SELECT `Item`.`id`, `Item`.`name`, `Item`.`code`' +
|
|
121
|
+
', (SELECT COUNT(*) `count` FROM `ItemTag` WHERE `ItemTag`.`itemId` = `Item`.`id`) `tagsCount`' +
|
|
122
|
+
', `measureUnit`.`id` `measureUnit.id`, `measureUnit`.`name` `measureUnit.name`, `measureUnit`.`categoryId` `measureUnit.categoryId`' +
|
|
123
|
+
', `measureUnit.category`.`id` `measureUnit.category.id`, `measureUnit.category`.`name` `measureUnit.category.name`' +
|
|
124
|
+
' FROM `Item` LEFT JOIN `MeasureUnit` `measureUnit` ON `measureUnit`.`id` = `Item`.`measureUnitId`' +
|
|
125
|
+
' LEFT JOIN `MeasureUnitCategory` `measureUnit.category` ON `measureUnit.category`.`id` = `measureUnit`.`categoryId`' +
|
|
126
|
+
' LIMIT 100');
|
|
127
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
128
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
129
|
+
jest.clearAllMocks();
|
|
130
|
+
await this.querier.findMany(test_1.Tag, {
|
|
131
|
+
$project: {
|
|
132
|
+
id: 1,
|
|
133
|
+
itemsCount: 1,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
expect(this.querier.all).toBeCalledWith('SELECT `id`, (SELECT COUNT(*) `count` FROM `ItemTag` WHERE `ItemTag`.`tagId` = `id`) `itemsCount` FROM `Tag`');
|
|
137
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
138
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
139
|
+
}
|
|
140
|
+
async shouldFind$exists() {
|
|
141
|
+
await this.querier.findMany(test_1.Item, {
|
|
142
|
+
$project: {
|
|
143
|
+
id: 1,
|
|
144
|
+
},
|
|
145
|
+
$filter: {
|
|
146
|
+
$exists: (0, raw_1.raw)(({ escapedPrefix, dialect }) => dialect.find(test_1.User, {
|
|
147
|
+
$project: ['id'],
|
|
148
|
+
$filter: { companyId: (0, raw_1.raw)(escapedPrefix + dialect.escapeId(`companyId`)) },
|
|
149
|
+
}, { autoPrefix: true })),
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
expect(this.querier.all).toBeCalledWith('SELECT `id` FROM `Item` WHERE EXISTS (SELECT `User`.`id` FROM `User` WHERE `User`.`companyId` = `Item`.`companyId`)');
|
|
153
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
154
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
155
|
+
}
|
|
156
|
+
async shouldFind$nexists() {
|
|
157
|
+
await this.querier.findMany(test_1.Item, {
|
|
158
|
+
$project: {
|
|
159
|
+
id: 1,
|
|
160
|
+
},
|
|
161
|
+
$filter: {
|
|
162
|
+
$nexists: (0, raw_1.raw)(({ escapedPrefix, dialect }) => dialect.find(test_1.User, {
|
|
163
|
+
$project: ['id'],
|
|
164
|
+
$filter: { companyId: (0, raw_1.raw)(escapedPrefix + dialect.escapeId(`companyId`)) },
|
|
165
|
+
}, { autoPrefix: true })),
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
expect(this.querier.all).toBeCalledWith('SELECT `id` FROM `Item` WHERE NOT EXISTS (SELECT `User`.`id` FROM `User` WHERE `User`.`companyId` = `Item`.`companyId`)');
|
|
169
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
170
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
171
|
+
}
|
|
172
|
+
async shouldFindOneAndProjectOneToManyOnly() {
|
|
173
|
+
await this.querier.insertMany(test_1.InventoryAdjustment, [
|
|
174
|
+
{
|
|
175
|
+
id: 123,
|
|
176
|
+
createdAt: 1,
|
|
177
|
+
},
|
|
178
|
+
{ id: 456, createdAt: 1 },
|
|
179
|
+
]);
|
|
180
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `InventoryAdjustment` (`id`, `createdAt`) VALUES (123, 1), (456, 1)');
|
|
181
|
+
await this.querier.findMany(test_1.InventoryAdjustment, {
|
|
182
|
+
$project: { itemAdjustments: ['id', 'buyPrice', 'itemId', 'creatorId', 'createdAt'] },
|
|
183
|
+
$filter: { createdAt: 1 },
|
|
184
|
+
});
|
|
185
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `InventoryAdjustment`.`id` FROM `InventoryAdjustment` WHERE `InventoryAdjustment`.`createdAt` = 1');
|
|
186
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id`, `buyPrice`, `itemId`, `creatorId`, `createdAt`, `inventoryAdjustmentId`' +
|
|
187
|
+
' FROM `ItemAdjustment` WHERE `inventoryAdjustmentId` IN (123, 456)');
|
|
188
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
189
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
190
|
+
}
|
|
191
|
+
async shouldFindOneAndProjectOneToManyWithSpecifiedFields() {
|
|
192
|
+
await this.querier.insertMany(test_1.InventoryAdjustment, [
|
|
193
|
+
{
|
|
194
|
+
description: 'something a',
|
|
195
|
+
createdAt: 1,
|
|
196
|
+
itemAdjustments: [
|
|
197
|
+
{ buyPrice: 1, createdAt: 1 },
|
|
198
|
+
{ buyPrice: 1, createdAt: 1 },
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
description: 'something b',
|
|
203
|
+
createdAt: 1,
|
|
204
|
+
itemAdjustments: [
|
|
205
|
+
{ id: 1, buyPrice: 1, updatedAt: 1 },
|
|
206
|
+
{ buyPrice: 1, createdAt: 1 },
|
|
207
|
+
],
|
|
208
|
+
},
|
|
209
|
+
]);
|
|
210
|
+
expect(this.querier.run).nthCalledWith(1, "INSERT INTO `InventoryAdjustment` (`description`, `createdAt`) VALUES ('something a', 1), ('something b', 1)");
|
|
211
|
+
expect(this.querier.run).nthCalledWith(2, 'INSERT INTO `ItemAdjustment` (`buyPrice`, `createdAt`, `inventoryAdjustmentId`) VALUES (1, 1, 1), (1, 1, 1)');
|
|
212
|
+
expect(this.querier.run).nthCalledWith(3, 'INSERT INTO `ItemAdjustment` (`buyPrice`, `createdAt`, `inventoryAdjustmentId`) VALUES (1, 1, 2)');
|
|
213
|
+
expect(this.querier.run).nthCalledWith(4, 'UPDATE `ItemAdjustment` SET `buyPrice` = 1, `updatedAt` = 1, `inventoryAdjustmentId` = 2 WHERE `id` = 1');
|
|
214
|
+
await this.querier.findMany(test_1.InventoryAdjustment, {
|
|
215
|
+
$project: { id: true, itemAdjustments: ['buyPrice'] },
|
|
216
|
+
$filter: { createdAt: 1 },
|
|
217
|
+
});
|
|
218
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `InventoryAdjustment`.`id` FROM `InventoryAdjustment` WHERE `InventoryAdjustment`.`createdAt` = 1');
|
|
219
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `buyPrice`, `inventoryAdjustmentId` FROM `ItemAdjustment` WHERE `inventoryAdjustmentId` IN (1, 2)');
|
|
220
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
221
|
+
expect(this.querier.run).toBeCalledTimes(4);
|
|
222
|
+
}
|
|
223
|
+
async shouldFindManyAndProjectOneToMany() {
|
|
224
|
+
await this.querier.insertMany(test_1.InventoryAdjustment, [
|
|
225
|
+
{ id: 123, description: 'something a', createdAt: 1 },
|
|
226
|
+
{ id: 456, description: 'something b', createdAt: 1 },
|
|
227
|
+
]);
|
|
228
|
+
expect(this.querier.run).nthCalledWith(1, "INSERT INTO `InventoryAdjustment` (`id`, `description`, `createdAt`) VALUES (123, 'something a', 1), (456, 'something b', 1)");
|
|
229
|
+
await this.querier.findMany(test_1.InventoryAdjustment, {
|
|
230
|
+
$project: { id: true, itemAdjustments: true },
|
|
231
|
+
$filter: { createdAt: 1 },
|
|
232
|
+
});
|
|
233
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `InventoryAdjustment`.`id` FROM `InventoryAdjustment` WHERE `InventoryAdjustment`.`createdAt` = 1');
|
|
234
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id`, `companyId`, `creatorId`, `createdAt`, `updatedAt`, `itemId`, `number`, `buyPrice`, `storehouseId`' +
|
|
235
|
+
', `inventoryAdjustmentId` FROM `ItemAdjustment` WHERE `inventoryAdjustmentId` IN (123, 456)');
|
|
236
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
237
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
238
|
+
}
|
|
239
|
+
async shouldFindOneAndProjectManyToMany() {
|
|
240
|
+
await this.querier.insertOne(test_1.Item, { id: 123, createdAt: 1 });
|
|
241
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `Item` (`id`, `createdAt`) VALUES (123, 1)');
|
|
242
|
+
await this.querier.findOne(test_1.Item, {
|
|
243
|
+
$project: { id: true, createdAt: true, tags: ['id'] },
|
|
244
|
+
});
|
|
245
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `Item`.`id`, `Item`.`createdAt` FROM `Item` LIMIT 1');
|
|
246
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `ItemTag`.`id`, `ItemTag`.`itemId`, `tag`.`id` `tag.id`' +
|
|
247
|
+
' FROM `ItemTag` INNER JOIN `Tag` `tag` ON `tag`.`id` = `ItemTag`.`tagId`' +
|
|
248
|
+
' WHERE `ItemTag`.`itemId` IN (123)');
|
|
249
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
250
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
251
|
+
}
|
|
252
|
+
async shouldFindOneByIdAndProjectManyToMany() {
|
|
253
|
+
await this.querier.insertOne(test_1.Item, { id: 123, createdAt: 1 });
|
|
254
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `Item` (`id`, `createdAt`) VALUES (123, 1)');
|
|
255
|
+
await this.querier.findOneById(test_1.Item, 123, {
|
|
256
|
+
$project: { id: 1, createdAt: 1, tags: ['id'] },
|
|
257
|
+
});
|
|
258
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `Item`.`id`, `Item`.`createdAt` FROM `Item` WHERE `Item`.`id` = 123 LIMIT 1');
|
|
259
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `ItemTag`.`id`, `ItemTag`.`itemId`, `tag`.`id` `tag.id`' +
|
|
260
|
+
' FROM `ItemTag` INNER JOIN `Tag` `tag` ON `tag`.`id` = `ItemTag`.`tagId`' +
|
|
261
|
+
' WHERE `ItemTag`.`itemId` IN (123)');
|
|
262
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
263
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
264
|
+
}
|
|
265
|
+
async shouldFindMany() {
|
|
266
|
+
await this.querier.findMany(test_1.User, {
|
|
267
|
+
$project: { id: true, name: true },
|
|
268
|
+
$filter: { companyId: 123 },
|
|
269
|
+
$limit: 100,
|
|
270
|
+
});
|
|
271
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id`, `name` FROM `User` WHERE `companyId` = 123 LIMIT 100');
|
|
272
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
273
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
274
|
+
}
|
|
275
|
+
async shouldFindManyAndCount() {
|
|
276
|
+
await this.querier.findManyAndCount(test_1.User, {
|
|
277
|
+
$project: { id: true, name: true },
|
|
278
|
+
$filter: { companyId: 123 },
|
|
279
|
+
$sort: { createdAt: -1 },
|
|
280
|
+
$skip: 50,
|
|
281
|
+
$limit: 100,
|
|
282
|
+
});
|
|
283
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id`, `name` FROM `User` WHERE `companyId` = 123 ORDER BY `createdAt` DESC LIMIT 100 OFFSET 50');
|
|
284
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT COUNT(*) `count` FROM `User` WHERE `companyId` = 123');
|
|
285
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
286
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
287
|
+
}
|
|
288
|
+
async shouldInsertOne() {
|
|
289
|
+
await this.querier.insertOne(test_1.User, { companyId: 123, createdAt: 1 });
|
|
290
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `User` (`companyId`, `createdAt`) VALUES (123, 1)');
|
|
291
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
292
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
293
|
+
}
|
|
294
|
+
async shouldInsertOneAndCascadeOneToOne() {
|
|
295
|
+
await this.querier.insertOne(test_1.User, {
|
|
296
|
+
name: 'some name',
|
|
297
|
+
createdAt: 1,
|
|
298
|
+
profile: { picture: 'abc', createdAt: 1 },
|
|
299
|
+
});
|
|
300
|
+
expect(this.querier.run).nthCalledWith(1, "INSERT INTO `User` (`name`, `createdAt`) VALUES ('some name', 1)");
|
|
301
|
+
expect(this.querier.run).nthCalledWith(2, "INSERT INTO `user_profile` (`image`, `createdAt`, `creatorId`) VALUES ('abc', 1, 1)");
|
|
302
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
303
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
304
|
+
}
|
|
305
|
+
async shouldInsertOneAndCascadeManyToOne() {
|
|
306
|
+
await this.querier.insertOne(test_1.MeasureUnit, {
|
|
307
|
+
name: 'Centimeter',
|
|
308
|
+
createdAt: 123,
|
|
309
|
+
category: { name: 'Metric', createdAt: 123 },
|
|
310
|
+
});
|
|
311
|
+
expect(this.querier.run).nthCalledWith(1, "INSERT INTO `MeasureUnit` (`name`, `createdAt`) VALUES ('Centimeter', 123)");
|
|
312
|
+
expect(this.querier.run).nthCalledWith(2, "INSERT INTO `MeasureUnitCategory` (`name`, `createdAt`) VALUES ('Metric', 123)");
|
|
313
|
+
expect(this.querier.run).nthCalledWith(3, expect.toMatch(/^UPDATE `MeasureUnit` SET `categoryId` = 1, `updatedAt` = \d+ WHERE `id` = 1 AND `deletedAt` IS NULL$/));
|
|
314
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
315
|
+
expect(this.querier.run).toBeCalledTimes(3);
|
|
316
|
+
}
|
|
317
|
+
async shouldInsertOneAndCascadeOneToMany() {
|
|
318
|
+
await this.querier.insertOne(test_1.InventoryAdjustment, {
|
|
319
|
+
description: 'some description',
|
|
320
|
+
createdAt: 1,
|
|
321
|
+
itemAdjustments: [
|
|
322
|
+
{ buyPrice: 50, createdAt: 1 },
|
|
323
|
+
{ buyPrice: 300, createdAt: 1 },
|
|
324
|
+
],
|
|
325
|
+
});
|
|
326
|
+
expect(this.querier.run).nthCalledWith(1, "INSERT INTO `InventoryAdjustment` (`description`, `createdAt`) VALUES ('some description', 1)");
|
|
327
|
+
expect(this.querier.run).nthCalledWith(2, 'INSERT INTO `ItemAdjustment` (`buyPrice`, `createdAt`, `inventoryAdjustmentId`) VALUES (50, 1, 1), (300, 1, 1)');
|
|
328
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
329
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
330
|
+
}
|
|
331
|
+
async shouldUpdateMany() {
|
|
332
|
+
await this.querier.updateMany(test_1.User, { $filter: { companyId: 4 } }, { name: 'Hola', updatedAt: 1 });
|
|
333
|
+
expect(this.querier.run).nthCalledWith(1, "UPDATE `User` SET `name` = 'Hola', `updatedAt` = 1 WHERE `companyId` = 4");
|
|
334
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
335
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
336
|
+
}
|
|
337
|
+
async shouldUpdateOneById() {
|
|
338
|
+
await this.querier.updateOneById(test_1.User, 5, { companyId: 123, updatedAt: 1 });
|
|
339
|
+
expect(this.querier.run).nthCalledWith(1, 'UPDATE `User` SET `companyId` = 123, `updatedAt` = 1 WHERE `id` = 5');
|
|
340
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
341
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
342
|
+
}
|
|
343
|
+
async shouldUpdateOneByIdAndCascadeOneToOne() {
|
|
344
|
+
await this.querier.insertOne(test_1.User, { createdAt: 1 });
|
|
345
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `User` (`createdAt`) VALUES (1)');
|
|
346
|
+
await this.querier.updateOneById(test_1.User, 1, {
|
|
347
|
+
name: 'something',
|
|
348
|
+
updatedAt: 1,
|
|
349
|
+
profile: { picture: 'xyz', createdAt: 1 },
|
|
350
|
+
});
|
|
351
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `User` SET `name` = 'something', `updatedAt` = 1 WHERE `id` = 1");
|
|
352
|
+
expect(this.querier.run).nthCalledWith(3, "INSERT INTO `user_profile` (`image`, `createdAt`, `creatorId`) VALUES ('xyz', 1, 1)");
|
|
353
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `User` WHERE `id` = 1');
|
|
354
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
355
|
+
expect(this.querier.run).toBeCalledTimes(3);
|
|
356
|
+
}
|
|
357
|
+
async shouldUpdateOneByIdAndCascadeOneToOneNull() {
|
|
358
|
+
await this.querier.insertOne(test_1.User, { createdAt: 1 });
|
|
359
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `User` (`createdAt`) VALUES (1)');
|
|
360
|
+
await this.querier.updateOneById(test_1.User, 1, {
|
|
361
|
+
name: 'something',
|
|
362
|
+
updatedAt: 1,
|
|
363
|
+
profile: null,
|
|
364
|
+
});
|
|
365
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `User` SET `name` = 'something', `updatedAt` = 1 WHERE `id` = 1");
|
|
366
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `User` WHERE `id` = 1');
|
|
367
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `pk` `id` FROM `user_profile` WHERE `creatorId` = 1');
|
|
368
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
369
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
370
|
+
}
|
|
371
|
+
async shouldUpdateOneByIdAndCascadeOneToMany() {
|
|
372
|
+
await this.querier.insertOne(test_1.InventoryAdjustment, { createdAt: 1 });
|
|
373
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `InventoryAdjustment` (`createdAt`) VALUES (1)');
|
|
374
|
+
await this.querier.updateOneById(test_1.InventoryAdjustment, 1, {
|
|
375
|
+
description: 'some description',
|
|
376
|
+
updatedAt: 1,
|
|
377
|
+
itemAdjustments: [
|
|
378
|
+
{ buyPrice: 50, createdAt: 1 },
|
|
379
|
+
{ buyPrice: 300, createdAt: 1 },
|
|
380
|
+
],
|
|
381
|
+
});
|
|
382
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `InventoryAdjustment` SET `description` = 'some description', `updatedAt` = 1 WHERE `id` = 1");
|
|
383
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `InventoryAdjustment` WHERE `id` = 1');
|
|
384
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id` FROM `ItemAdjustment` WHERE `inventoryAdjustmentId` = 1');
|
|
385
|
+
expect(this.querier.run).nthCalledWith(3, 'INSERT INTO `ItemAdjustment` (`buyPrice`, `createdAt`, `inventoryAdjustmentId`) VALUES (50, 1, 1), (300, 1, 1)');
|
|
386
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
387
|
+
expect(this.querier.run).toBeCalledTimes(3);
|
|
388
|
+
}
|
|
389
|
+
async shouldUpdateOneByIdAndCascadeOneToManyNull() {
|
|
390
|
+
await this.querier.insertOne(test_1.InventoryAdjustment, { createdAt: 1 });
|
|
391
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `InventoryAdjustment` (`createdAt`) VALUES (1)');
|
|
392
|
+
await this.querier.updateOneById(test_1.InventoryAdjustment, 1, {
|
|
393
|
+
description: 'some description',
|
|
394
|
+
updatedAt: 1,
|
|
395
|
+
itemAdjustments: null,
|
|
396
|
+
});
|
|
397
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `InventoryAdjustment` SET `description` = 'some description', `updatedAt` = 1 WHERE `id` = 1");
|
|
398
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `InventoryAdjustment` WHERE `id` = 1');
|
|
399
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id` FROM `ItemAdjustment` WHERE `inventoryAdjustmentId` = 1');
|
|
400
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
401
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
402
|
+
}
|
|
403
|
+
async shouldUpdateManyAndCascadeOneToManyNull() {
|
|
404
|
+
await this.querier.insertOne(test_1.InventoryAdjustment, { companyId: 1, createdAt: 1 });
|
|
405
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `InventoryAdjustment` (`companyId`, `createdAt`) VALUES (1, 1)');
|
|
406
|
+
await this.querier.updateMany(test_1.InventoryAdjustment, { $filter: { companyId: 1 } }, {
|
|
407
|
+
description: 'some description',
|
|
408
|
+
updatedAt: 1,
|
|
409
|
+
itemAdjustments: null,
|
|
410
|
+
});
|
|
411
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `InventoryAdjustment` SET `description` = 'some description', `updatedAt` = 1 WHERE `companyId` = 1");
|
|
412
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `InventoryAdjustment` WHERE `companyId` = 1');
|
|
413
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id` FROM `ItemAdjustment` WHERE `inventoryAdjustmentId` = 1');
|
|
414
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
415
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
416
|
+
}
|
|
417
|
+
async shouldInsertOneAndCascadeManyToManyInserts() {
|
|
418
|
+
await this.querier.insertOne(test_1.Item, {
|
|
419
|
+
name: 'item one',
|
|
420
|
+
createdAt: 1,
|
|
421
|
+
tags: [
|
|
422
|
+
{
|
|
423
|
+
name: 'tag one',
|
|
424
|
+
createdAt: 1,
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
name: 'tag two',
|
|
428
|
+
createdAt: 1,
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
});
|
|
432
|
+
expect(this.querier.run).nthCalledWith(1, "INSERT INTO `Item` (`name`, `createdAt`) VALUES ('item one', 1)");
|
|
433
|
+
expect(this.querier.run).nthCalledWith(2, "INSERT INTO `Tag` (`name`, `createdAt`) VALUES ('tag one', 1), ('tag two', 1)");
|
|
434
|
+
expect(this.querier.run).nthCalledWith(3, 'INSERT INTO `ItemTag` (`itemId`, `tagId`) VALUES (1, 1), (1, 2)');
|
|
435
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
436
|
+
expect(this.querier.run).toBeCalledTimes(3);
|
|
437
|
+
}
|
|
438
|
+
async shouldUpdateAndCascadeManyToManyInserts() {
|
|
439
|
+
const id = await this.querier.insertOne(test_1.Item, { createdAt: 1 });
|
|
440
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `Item` (`createdAt`) VALUES (1)');
|
|
441
|
+
await this.querier.updateOneById(test_1.Item, id, {
|
|
442
|
+
name: 'item one',
|
|
443
|
+
updatedAt: 1,
|
|
444
|
+
tags: [
|
|
445
|
+
{
|
|
446
|
+
name: 'tag one',
|
|
447
|
+
createdAt: 1,
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
name: 'tag two',
|
|
451
|
+
createdAt: 1,
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
});
|
|
455
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `Item` SET `name` = 'item one', `updatedAt` = 1 WHERE `id` = 1");
|
|
456
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `Item` WHERE `id` = 1');
|
|
457
|
+
expect(this.querier.run).nthCalledWith(3, "INSERT INTO `Tag` (`name`, `createdAt`) VALUES ('tag one', 1), ('tag two', 1)");
|
|
458
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id` FROM `ItemTag` WHERE `itemId` = 1');
|
|
459
|
+
expect(this.querier.run).nthCalledWith(4, 'INSERT INTO `ItemTag` (`itemId`, `tagId`) VALUES (1, 1), (1, 2)');
|
|
460
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
461
|
+
expect(this.querier.run).toBeCalledTimes(4);
|
|
462
|
+
}
|
|
463
|
+
async shouldUpdateAndCascadeManyToManyLinks() {
|
|
464
|
+
const id = await this.querier.insertOne(test_1.Item, { createdAt: 1 });
|
|
465
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `Item` (`createdAt`) VALUES (1)');
|
|
466
|
+
await this.querier.updateOneById(test_1.Item, id, {
|
|
467
|
+
name: 'item one',
|
|
468
|
+
tags: [{ id: 22 }, { id: 33 }],
|
|
469
|
+
updatedAt: 1,
|
|
470
|
+
});
|
|
471
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `Item` SET `name` = 'item one', `updatedAt` = 1 WHERE `id` = 1");
|
|
472
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `Item` WHERE `id` = 1');
|
|
473
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id` FROM `ItemTag` WHERE `itemId` = 1');
|
|
474
|
+
expect(this.querier.run).nthCalledWith(3, 'INSERT INTO `ItemTag` (`itemId`, `tagId`) VALUES (1, 22), (1, 33)');
|
|
475
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
476
|
+
expect(this.querier.run).toBeCalledTimes(3);
|
|
477
|
+
}
|
|
478
|
+
async shouldDeleteOneAndCascadeManyToManyDeletes() {
|
|
479
|
+
await this.shouldInsertOneAndCascadeManyToManyInserts();
|
|
480
|
+
jest.clearAllMocks();
|
|
481
|
+
await this.querier.deleteOneById(test_1.Item, 1);
|
|
482
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `Item` WHERE `id` = 1');
|
|
483
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `id` FROM `ItemTag` WHERE `itemId` IN (1)');
|
|
484
|
+
expect(this.querier.run).nthCalledWith(1, 'DELETE FROM `Item` WHERE `id` IN (1)');
|
|
485
|
+
expect(this.querier.run).nthCalledWith(2, 'DELETE FROM `ItemTag` WHERE `id` IN (1, 2)');
|
|
486
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
487
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
488
|
+
}
|
|
489
|
+
async shouldDeleteOneAndNoCascadeManyToManyDeletes() {
|
|
490
|
+
await this.shouldInsertOneAndCascadeManyToManyInserts();
|
|
491
|
+
jest.clearAllMocks();
|
|
492
|
+
await this.querier.deleteOneById(test_1.Tag, 1);
|
|
493
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `Tag` WHERE `id` = 1');
|
|
494
|
+
expect(this.querier.run).nthCalledWith(1, 'DELETE FROM `Tag` WHERE `id` IN (1)');
|
|
495
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
496
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
497
|
+
}
|
|
498
|
+
async shouldDeleteOneById() {
|
|
499
|
+
const id = await this.querier.insertOne(test_1.User, { createdAt: 1, profile: { createdAt: 1 } });
|
|
500
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `User` (`createdAt`) VALUES (1)');
|
|
501
|
+
expect(this.querier.run).nthCalledWith(2, 'INSERT INTO `user_profile` (`createdAt`, `creatorId`) VALUES (1, 1)');
|
|
502
|
+
await this.querier.deleteOneById(test_1.User, id);
|
|
503
|
+
expect(this.querier.run).nthCalledWith(3, 'DELETE FROM `User` WHERE `id` IN (1)');
|
|
504
|
+
expect(this.querier.run).nthCalledWith(4, 'DELETE FROM `user_profile` WHERE `pk` IN (1)');
|
|
505
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `User` WHERE `id` = 1');
|
|
506
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `pk` `id` FROM `user_profile`');
|
|
507
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
508
|
+
expect(this.querier.run).toBeCalledTimes(4);
|
|
509
|
+
}
|
|
510
|
+
async shouldDeleteMany() {
|
|
511
|
+
await this.querier.insertOne(test_1.User, { createdAt: 123 });
|
|
512
|
+
expect(this.querier.run).nthCalledWith(1, 'INSERT INTO `User` (`createdAt`) VALUES (123)');
|
|
513
|
+
await this.querier.deleteMany(test_1.User, { $filter: { createdAt: 123 } });
|
|
514
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT `id` FROM `User` WHERE `createdAt` = 123');
|
|
515
|
+
expect(this.querier.all).nthCalledWith(2, 'SELECT `pk` `id` FROM `user_profile`');
|
|
516
|
+
expect(this.querier.run).nthCalledWith(2, 'DELETE FROM `User` WHERE `id` IN (1)');
|
|
517
|
+
expect(this.querier.all).toBeCalledTimes(2);
|
|
518
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
519
|
+
}
|
|
520
|
+
async shouldCount() {
|
|
521
|
+
await this.querier.count(test_1.User, { $filter: { companyId: 123 } });
|
|
522
|
+
expect(this.querier.all).nthCalledWith(1, 'SELECT COUNT(*) `count` FROM `User` WHERE `companyId` = 123');
|
|
523
|
+
expect(this.querier.all).toBeCalledTimes(1);
|
|
524
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
525
|
+
}
|
|
526
|
+
async shouldUseTransaction() {
|
|
527
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
528
|
+
await this.querier.beginTransaction();
|
|
529
|
+
expect(this.querier.run).toBeCalledWith(this.querier.dialect.beginTransactionCommand);
|
|
530
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
531
|
+
await this.querier.updateOneById(test_1.User, 5, { name: 'Hola', updatedAt: 1 });
|
|
532
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
533
|
+
await this.querier.commitTransaction();
|
|
534
|
+
expect(this.querier.run).nthCalledWith(1, this.querier.dialect.beginTransactionCommand);
|
|
535
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `User` SET `name` = 'Hola', `updatedAt` = 1 WHERE `id` = 5");
|
|
536
|
+
expect(this.querier.run).nthCalledWith(3, 'COMMIT');
|
|
537
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
538
|
+
await this.querier.release();
|
|
539
|
+
expect(this.querier.run).toBeCalledTimes(3);
|
|
540
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
541
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
542
|
+
}
|
|
543
|
+
async shouldUseTransactionCallback() {
|
|
544
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
545
|
+
await this.querier.transaction(async () => {
|
|
546
|
+
expect(this.querier.run).toBeCalledWith(this.querier.dialect.beginTransactionCommand);
|
|
547
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
548
|
+
await this.querier.updateOneById(test_1.User, 5, { name: 'Hola', updatedAt: 1 });
|
|
549
|
+
});
|
|
550
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
551
|
+
expect(this.querier.run).nthCalledWith(1, this.querier.dialect.beginTransactionCommand);
|
|
552
|
+
expect(this.querier.run).nthCalledWith(2, "UPDATE `User` SET `name` = 'Hola', `updatedAt` = 1 WHERE `id` = 5");
|
|
553
|
+
expect(this.querier.run).nthCalledWith(3, 'COMMIT');
|
|
554
|
+
expect(this.querier.run).toBeCalledTimes(3);
|
|
555
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
556
|
+
}
|
|
557
|
+
async shouldThrowIfRollbackIfErrorInCallback() {
|
|
558
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
559
|
+
const prom = this.querier.transaction(async () => {
|
|
560
|
+
expect(this.querier.run).toBeCalledWith(this.querier.dialect.beginTransactionCommand);
|
|
561
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
562
|
+
throw new Error('some error');
|
|
563
|
+
});
|
|
564
|
+
await expect(prom).rejects.toThrow('some error');
|
|
565
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
566
|
+
expect(this.querier.run).nthCalledWith(1, this.querier.dialect.beginTransactionCommand);
|
|
567
|
+
expect(this.querier.run).nthCalledWith(2, 'ROLLBACK');
|
|
568
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
569
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
570
|
+
}
|
|
571
|
+
async shouldThrowIfTransactionIsPending() {
|
|
572
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
573
|
+
await this.querier.beginTransaction();
|
|
574
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
575
|
+
await expect(this.querier.beginTransaction()).rejects.toThrow('pending transaction');
|
|
576
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
577
|
+
expect(this.querier.run).toBeCalledTimes(1);
|
|
578
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
579
|
+
await this.querier.rollbackTransaction();
|
|
580
|
+
}
|
|
581
|
+
async shouldThrowIfCommitWithNoPendingTransaction() {
|
|
582
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
583
|
+
await expect(this.querier.commitTransaction()).rejects.toThrow('pending transaction');
|
|
584
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
585
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
586
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
587
|
+
}
|
|
588
|
+
async shouldThrowIfRollbackWithNoPendingTransaction() {
|
|
589
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
590
|
+
await expect(this.querier.rollbackTransaction()).rejects.toThrow('not a pending transaction');
|
|
591
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
592
|
+
expect(this.querier.run).toBeCalledTimes(0);
|
|
593
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
594
|
+
}
|
|
595
|
+
async shouldThrowIfReleaseWithPendingTransaction() {
|
|
596
|
+
expect(this.querier.hasOpenTransaction).toBeFalsy();
|
|
597
|
+
await this.querier.beginTransaction();
|
|
598
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
599
|
+
await this.querier.updateOneById(test_1.User, 5, { name: 'some name' });
|
|
600
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
601
|
+
await expect(this.querier.release()).rejects.toThrow('pending transaction');
|
|
602
|
+
expect(this.querier.hasOpenTransaction).toBe(true);
|
|
603
|
+
expect(this.querier.run).toBeCalledTimes(2);
|
|
604
|
+
expect(this.querier.all).toBeCalledTimes(0);
|
|
605
|
+
await this.querier.rollbackTransaction();
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
exports.AbstractSqlQuerierSpec = AbstractSqlQuerierSpec;
|
|
609
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3RTcWxRdWVyaWVyLXNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcXVlcmllci9hYnN0cmFjdFNxbFF1ZXJpZXItc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw0Q0FBeUM7QUFDekMseUNBQWdJO0FBSWhJLE1BQXNCLHNCQUFzQjtJQUcxQyxZQUFxQixJQUFxQyxFQUFXLE1BQWM7UUFBOUQsU0FBSSxHQUFKLElBQUksQ0FBaUM7UUFBVyxXQUFNLEdBQU4sTUFBTSxDQUFRO0lBQUcsQ0FBQztJQUV2RixLQUFLLENBQUMsU0FBUztRQUNiLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzVDLE1BQU0sSUFBQSxpQkFBVSxFQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQixNQUFNLElBQUEsbUJBQVksRUFBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVO1FBQ2QsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDNUMsTUFBTSxJQUFBLGtCQUFXLEVBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVELEtBQUssQ0FBQyxTQUFTO1FBQ2IsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FB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QUMsYUFBYSxDQUFDLFdBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUNqRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRCxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQzVFLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25ELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUMsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLG1CQUFtQixFQUFFLENBQUM7SUFDM0MsQ0FBQztDQUNGO0FBdnpCRCx3REF1ekJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmF3IH0gZnJvbSAnQHVxbC9jb3JlL3V0aWwvcmF3JztcbmltcG9ydCB7IFVzZXIsIEludmVudG9yeUFkanVzdG1lbnQsIFNwZWMsIEl0ZW0sIFRhZywgTWVhc3VyZVVuaXQsIGRyb3BUYWJsZXMsIGNyZWF0ZVRhYmxlcywgY2xlYXJUYWJsZXMgfSBmcm9tICdAdXFsL2NvcmUvdGVzdCc7XG5pbXBvcnQgeyBRdWVyaWVyUG9vbCB9IGZyb20gJ0B1cWwvY29yZS90eXBlJztcbmltcG9ydCB7IEFic3RyYWN0U3FsUXVlcmllciB9IGZyb20gJy4vYWJzdHJhY3RTcWxRdWVyaWVyJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEFic3RyYWN0U3FsUXVlcmllclNwZWMgaW1wbGVtZW50cyBTcGVjIHtcbiAgcXVlcmllcjogQWJzdHJhY3RTcWxRdWVyaWVyO1xuXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IHBvb2w6IFF1ZXJpZXJQb29sPEFic3RyYWN0U3FsUXVlcmllcj4sIHJlYWRvbmx5IGlkVHlwZTogc3RyaW5nKSB7fVxuXG4gIGFzeW5jIGJlZm9yZUFsbCgpIHtcbiAgICB0aGlzLnF1ZXJpZXIgPSBhd2FpdCB0aGlzLnBvb2wuZ2V0UXVlcmllcigpO1xuICAgIGF3YWl0IGRyb3BUYWJsZXModGhpcy5xdWVyaWVyKTtcbiAgICBhd2FpdCBjcmVhdGVUYWJsZXModGhpcy5xdWVyaWVyLCB0aGlzLmlkVHlwZSk7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLnJlbGVhc2UoKTtcbiAgfVxuXG4gIGFzeW5jIGJlZm9yZUVhY2goKSB7XG4gICAgdGhpcy5xdWVyaWVyID0gYXdhaXQgdGhpcy5wb29sLmdldFF1ZXJpZXIoKTtcbiAgICBhd2FpdCBjbGVhclRhYmxlcyh0aGlzLnF1ZXJpZXIpO1xuICAgIGplc3Quc3B5T24odGhpcy5xdWVyaWVyLCAnYWxsJyk7XG4gICAgamVzdC5zcHlPbih0aGlzLnF1ZXJpZXIsICdydW4nKTtcbiAgfVxuXG4gIGFzeW5jIGFmdGVyRWFjaCgpIHtcbiAgICBqZXN0LnJlc3RvcmVBbGxNb2NrcygpO1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5yZWxlYXNlKCk7XG4gIH1cblxuICBhc3luYyBhZnRlckFsbCgpIHtcbiAgICBhd2FpdCB0aGlzLnBvb2wuZW5kKCk7XG4gIH1cblxuICBhc3luYyBzaG91bGRGaW5kT25lQnlJZCgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuZmluZE9uZUJ5SWQoVXNlciwgMSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoXG4gICAgICAxLFxuICAgICAgJ1NFTEVDVCBgaWRgLCBgY29tcGFueUlkYCwgYGNyZWF0b3JJZGAsIGBjcmVhdGVkQXRgLCBgdXBkYXRlZEF0YCwgYG5hbWVgLCBgZW1haWxgLCBgcGFzc3dvcmRgIEZST00gYFVzZXJgIFdIRVJFIGBpZGAgPSAxIExJTUlUIDEnXG4gICAgKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDEpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gIH1cblxuICBhc3luYyBzaG91bGRGaW5kT25lKCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5maW5kT25lKFVzZXIsIHsgJHByb2plY3Q6IFsnaWQnLCAnbmFtZSddLCAkZmlsdGVyOiB7IGNvbXBhbnlJZDogMTIzIH0gfSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMSwgJ1NFTEVDVCBgaWRgLCBgbmFtZWAgRlJPTSBgVXNlcmAgV0hFUkUgYGNvbXBhbnlJZGAgPSAxMjMgTElNSVQgMScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZEZpbmRPbmVBbmRQcm9qZWN0T25lVG9NYW55KCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5pbnNlcnRNYW55KEludmVudG9yeUFkanVzdG1lbnQsIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IDEyMyxcbiAgICAgICAgY3JlYXRlZEF0OiAxLFxuICAgICAgfSxcbiAgICAgIHsgaWQ6IDQ1NiwgY3JlYXRlZEF0OiAxIH0sXG4gICAgXSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnSU5TRVJUIElOVE8gYEludmVudG9yeUFkanVzdG1lbnRgIChgaWRgLCBgY3JlYXRlZEF0YCkgVkFMVUVTICgxMjMsIDEpLCAoNDU2LCAxKScpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmZpbmRNYW55KEludmVudG9yeUFkanVzdG1lbnQsIHtcbiAgICAgICRwcm9qZWN0OiBbJ2lkJywgJ2l0ZW1BZGp1c3RtZW50cyddLFxuICAgICAgJGZpbHRlcjogeyBjcmVhdGVkQXQ6IDEgfSxcbiAgICB9KTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKFxuICAgICAgMSxcbiAgICAgICdTRUxFQ1QgYEludmVudG9yeUFkanVzdG1lbnRgLmBpZGAgRlJPTSBgSW52ZW50b3J5QWRqdXN0bWVudGAgV0hFUkUgYEludmVudG9yeUFkanVzdG1lbnRgLmBjcmVhdGVkQXRgID0gMSdcbiAgICApO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKFxuICAgICAgMixcbiAgICAgICdTRUxFQ1QgYGlkYCwgYGNvbXBhbnlJZGAsIGBjcmVhdG9ySWRgLCBgY3JlYXRlZEF0YCwgYHVwZGF0ZWRBdGAsIGBpdGVtSWRgLCBgbnVtYmVyYCwgYGJ1eVByaWNlYCwgYHN0b3JlaG91c2VJZGAnICtcbiAgICAgICAgJywgYGludmVudG9yeUFkanVzdG1lbnRJZGAgRlJPTSBgSXRlbUFkanVzdG1lbnRgIFdIRVJFIGBpbnZlbnRvcnlBZGp1c3RtZW50SWRgIElOICgxMjMsIDQ1NiknXG4gICAgKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygxKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZEZpbmRBbmRQcm9qZWN0UmF3KCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5maW5kTWFueShJbnZlbnRvcnlBZGp1c3RtZW50LCB7XG4gICAgICAkcHJvamVjdDoge1xuICAgICAgICBjcmVhdG9yOiBbJ2lkJywgJ25hbWUnXSxcbiAgICAgICAgaXRlbUFkanVzdG1lbnRzOiB7XG4gICAgICAgICAgJHByb2plY3Q6IHtcbiAgICAgICAgICAgIGl0ZW06IHtcbiAgICAgICAgICAgICAgJHByb2plY3Q6IHtcbiAgICAgICAgICAgICAgICBjb21wYW55SWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgdG90YWw6IHJhdygoeyBlc2NhcGVkUHJlZml4LCBkaWFsZWN0IH0pID0+IGBTVU0oJHtlc2NhcGVkUHJlZml4fSR7ZGlhbGVjdC5lc2NhcGVJZCgnc2FsZVByaWNlJyl9KWApLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgICRzb3J0OiB7IGNyZWF0ZWRBdDogLTEgfSxcbiAgICAgICAgICAkbGltaXQ6IDEwMCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICAkZmlsdGVyOiB7XG4gICAgICAgIGNvbXBhbnlJZDogMSxcbiAgICAgIH0sXG4gICAgICAkc29ydDogeyBjcmVhdG9yOiB7IG5hbWU6ICdhc2MnIH0gfSxcbiAgICB9KTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKFxuICAgICAgMSxcbiAgICAgICdTRUxFQ1QgYEludmVudG9yeUFkanVzdG1lbnRgLmBpZGAsIGBjcmVhdG9yYC5gaWRgIGBjcmVhdG9yLmlkYCwgYGNyZWF0b3JgLmBuYW1lYCBgY3JlYXRvci5uYW1lYCcgK1xuICAgICAgICAnIEZST00gYEludmVudG9yeUFkanVzdG1lbnRgIExFRlQgSk9JTiBgVXNlcmAgYGNyZWF0b3JgIE9OIGBjcmVhdG9yYC5gaWRgID0gYEludmVudG9yeUFkanVzdG1lbnRgLmBjcmVhdG9ySWRgJyArXG4gICAgICAgICcgV0hFUkUgYEludmVudG9yeUFkanVzdG1lbnRgLmBjb21wYW55SWRgID0gMSBPUkRFUiBCWSBgY3JlYXRvcmAuYG5hbWVgJ1xuICAgICk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoXG4gICAgICAyLFxuICAgICAgJ1NFTEVDVCBgSXRlbUFkanVzdG1lbnRgLmBpZGAsIGBJdGVtQWRqdXN0bWVudGAuYGludmVudG9yeUFkanVzdG1lbnRJZGAnICtcbiAgICAgICAgJywgYGl0ZW1gLmBpZGAgYGl0ZW0uaWRgLCBgaXRlbWAuYGNvbXBhbnlJZGAgYGl0ZW0uY29tcGFueUlkYCwgU1VNKGBpdGVtYC5gc2FsZVByaWNlYCkgYGl0ZW0udG90YWxgJyArXG4gICAgICAgICcgRlJPTSBgSXRlbUFkanVzdG1lbnRgIExFRlQgSk9JTiBgSXRlbWAgYGl0ZW1gIE9OIGBpdGVtYC5gaWRgID0gYEl0ZW1BZGp1c3RtZW50YC5gaXRlbUlkYCcgK1xuICAgICAgICAnIFdIRVJFIGBJdGVtQWRqdXN0bWVudGAuYGludmVudG9yeUFkanVzdG1lbnRJZGAgSU4gKCknICtcbiAgICAgICAgJyBPUkRFUiBCWSBgSXRlbUFkanVzdG1lbnRgLmBjcmVhdGVkQXRgJyArXG4gICAgICAgICcgREVTQyBMSU1JVCAxMDAnXG4gICAgKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFZpcnR1YWxGaWVsZCgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuZmluZE1hbnkoSXRlbSwge1xuICAgICAgJHByb2plY3Q6IHtcbiAgICAgICAgaWQ6IDEsXG4gICAgICB9LFxuICAgICAgJGZpbHRlcjoge1xuICAgICAgICB0YWdzQ291bnQ6IHsgJGd0ZTogMTAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFdpdGgoXG4gICAgICAnU0VMRUNUIGBpZGAgRlJPTSBgSXRlbWAgV0hFUkUgKFNFTEVDVCBDT1VOVCgqKSBgY291bnRgIEZST00gYEl0ZW1UYWdgIFdIRVJFIGBJdGVtVGFnYC5gaXRlbUlkYCA9IGBpZGApID49IDEwJ1xuICAgICk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDEpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gICAgamVzdC5jbGVhckFsbE1vY2tzKCk7XG5cbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuZmluZE1hbnkoSXRlbSwge1xuICAgICAgJHByb2plY3Q6IHtcbiAgICAgICAgaWQ6IDEsXG4gICAgICAgIG5hbWU6IDEsXG4gICAgICAgIGNvZGU6IDEsXG4gICAgICAgIHRhZ3NDb3VudDogMSxcbiAgICAgICAgbWVhc3VyZVVuaXQ6IHtcbiAgICAgICAgICAkcHJvamVjdDogeyBpZDogMSwgbmFtZTogMSwgY2F0ZWdvcnlJZDogMSwgY2F0ZWdvcnk6IFsnbmFtZSddIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgJGxpbWl0OiAxMDAsXG4gICAgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFdpdGgoXG4gICAgICAnU0VMRUNUIGBJdGVtYC5gaWRgLCBgSXRlbWAuYG5hbWVgLCBgSXRlbWAuYGNvZGVgJyArXG4gICAgICAgICcsIChTRUxFQ1QgQ09VTlQoKikgYGNvdW50YCBGUk9NIGBJdGVtVGFnYCBXSEVSRSBgSXRlbVRhZ2AuYGl0ZW1JZGAgPSBgSXRlbWAuYGlkYCkgYHRhZ3NDb3VudGAnICtcbiAgICAgICAgJywgYG1lYXN1cmVVbml0YC5gaWRgIGBtZWFzdXJlVW5pdC5pZGAsIGBtZWFzdXJlVW5pdGAuYG5hbWVgIGBtZWFzdXJlVW5pdC5uYW1lYCwgYG1lYXN1cmVVbml0YC5gY2F0ZWdvcnlJZGAgYG1lYXN1cmVVbml0LmNhdGVnb3J5SWRgJyArXG4gICAgICAgICcsIGBtZWFzdXJlVW5pdC5jYXRlZ29yeWAuYGlkYCBgbWVhc3VyZVVuaXQuY2F0ZWdvcnkuaWRgLCBgbWVhc3VyZVVuaXQuY2F0ZWdvcnlgLmBuYW1lYCBgbWVhc3VyZVVuaXQuY2F0ZWdvcnkubmFtZWAnICtcbiAgICAgICAgJyBGUk9NIGBJdGVtYCBMRUZUIEpPSU4gYE1lYXN1cmVVbml0YCBgbWVhc3VyZVVuaXRgIE9OIGBtZWFzdXJlVW5pdGAuYGlkYCA9IGBJdGVtYC5gbWVhc3VyZVVuaXRJZGAnICtcbiAgICAgICAgJyBMRUZUIEpPSU4gYE1lYXN1cmVVbml0Q2F0ZWdvcnlgIGBtZWFzdXJlVW5pdC5jYXRlZ29yeWAgT04gYG1lYXN1cmVVbml0LmNhdGVnb3J5YC5gaWRgID0gYG1lYXN1cmVVbml0YC5gY2F0ZWdvcnlJZGAnICtcbiAgICAgICAgJyBMSU1JVCAxMDAnXG4gICAgKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygwKTtcblxuICAgIGplc3QuY2xlYXJBbGxNb2NrcygpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmZpbmRNYW55KFRhZywge1xuICAgICAgJHByb2plY3Q6IHtcbiAgICAgICAgaWQ6IDEsXG4gICAgICAgIGl0ZW1zQ291bnQ6IDEsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRXaXRoKFxuICAgICAgJ1NFTEVDVCBgaWRgLCAoU0VMRUNUIENPVU5UKCopIGBjb3VudGAgRlJPTSBgSXRlbVRhZ2AgV0hFUkUgYEl0ZW1UYWdgLmB0YWdJZGAgPSBgaWRgKSBgaXRlbXNDb3VudGAgRlJPTSBgVGFnYCdcbiAgICApO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygxKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDApO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkRmluZCRleGlzdHMoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmZpbmRNYW55KEl0ZW0sIHtcbiAgICAgICRwcm9qZWN0OiB7XG4gICAgICAgIGlkOiAxLFxuICAgICAgfSxcbiAgICAgICRmaWx0ZXI6IHtcbiAgICAgICAgJGV4aXN0czogcmF3KCh7IGVzY2FwZWRQcmVmaXgsIGRpYWxlY3QgfSkgPT5cbiAgICAgICAgICBkaWFsZWN0LmZpbmQoXG4gICAgICAgICAgICBVc2VyLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAkcHJvamVjdDogWydpZCddLFxuICAgICAgICAgICAgICAkZmlsdGVyOiB7IGNvbXBhbnlJZDogcmF3KGVzY2FwZWRQcmVmaXggKyBkaWFsZWN0LmVzY2FwZUlkKGBjb21wYW55SWRgKSkgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IGF1dG9QcmVmaXg6IHRydWUgfVxuICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFdpdGgoXG4gICAgICAnU0VMRUNUIGBpZGAgRlJPTSBgSXRlbWAgV0hFUkUgRVhJU1RTIChTRUxFQ1QgYFVzZXJgLmBpZGAgRlJPTSBgVXNlcmAgV0hFUkUgYFVzZXJgLmBjb21wYW55SWRgID0gYEl0ZW1gLmBjb21wYW55SWRgKSdcbiAgICApO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygxKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDApO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkRmluZCRuZXhpc3RzKCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5maW5kTWFueShJdGVtLCB7XG4gICAgICAkcHJvamVjdDoge1xuICAgICAgICBpZDogMSxcbiAgICAgIH0sXG4gICAgICAkZmlsdGVyOiB7XG4gICAgICAgICRuZXhpc3RzOiByYXcoKHsgZXNjYXBlZFByZWZpeCwgZGlhbGVjdCB9KSA9PlxuICAgICAgICAgIGRpYWxlY3QuZmluZChcbiAgICAgICAgICAgIFVzZXIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICRwcm9qZWN0OiBbJ2lkJ10sXG4gICAgICAgICAgICAgICRmaWx0ZXI6IHsgY29tcGFueUlkOiByYXcoZXNjYXBlZFByZWZpeCArIGRpYWxlY3QuZXNjYXBlSWQoYGNvbXBhbnlJZGApKSB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHsgYXV0b1ByZWZpeDogdHJ1ZSB9XG4gICAgICAgICAgKVxuICAgICAgICApLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkV2l0aChcbiAgICAgICdTRUxFQ1QgYGlkYCBGUk9NIGBJdGVtYCBXSEVSRSBOT1QgRVhJU1RTIChTRUxFQ1QgYFVzZXJgLmBpZGAgRlJPTSBgVXNlcmAgV0hFUkUgYFVzZXJgLmBjb21wYW55SWRgID0gYEl0ZW1gLmBjb21wYW55SWRgKSdcbiAgICApO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygxKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDApO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkRmluZE9uZUFuZFByb2plY3RPbmVUb01hbnlPbmx5KCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5pbnNlcnRNYW55KEludmVudG9yeUFkanVzdG1lbnQsIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IDEyMyxcbiAgICAgICAgY3JlYXRlZEF0OiAxLFxuICAgICAgfSxcbiAgICAgIHsgaWQ6IDQ1NiwgY3JlYXRlZEF0OiAxIH0sXG4gICAgXSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnSU5TRVJUIElOVE8gYEludmVudG9yeUFkanVzdG1lbnRgIChgaWRgLCBgY3JlYXRlZEF0YCkgVkFMVUVTICgxMjMsIDEpLCAoNDU2LCAxKScpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmZpbmRNYW55KEludmVudG9yeUFkanVzdG1lbnQsIHtcbiAgICAgICRwcm9qZWN0OiB7IGl0ZW1BZGp1c3RtZW50czogWydpZCcsICdidXlQcmljZScsICdpdGVtSWQnLCAnY3JlYXRvcklkJywgJ2NyZWF0ZWRBdCddIH0sXG4gICAgICAkZmlsdGVyOiB7IGNyZWF0ZWRBdDogMSB9LFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoXG4gICAgICAxLFxuICAgICAgJ1NFTEVDVCBgSW52ZW50b3J5QWRqdXN0bWVudGAuYGlkYCBGUk9NIGBJbnZlbnRvcnlBZGp1c3RtZW50YCBXSEVSRSBgSW52ZW50b3J5QWRqdXN0bWVudGAuYGNyZWF0ZWRBdGAgPSAxJ1xuICAgICk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoXG4gICAgICAyLFxuICAgICAgJ1NFTEVDVCBgaWRgLCBgYnV5UHJpY2VgLCBgaXRlbUlkYCwgYGNyZWF0b3JJZGAsIGBjcmVhdGVkQXRgLCBgaW52ZW50b3J5QWRqdXN0bWVudElkYCcgK1xuICAgICAgICAnIEZST00gYEl0ZW1BZGp1c3RtZW50YCBXSEVSRSBgaW52ZW50b3J5QWRqdXN0bWVudElkYCBJTiAoMTIzLCA0NTYpJ1xuICAgICk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gIH1cblxuICBhc3luYyBzaG91bGRGaW5kT25lQW5kUHJvamVjdE9uZVRvTWFueVdpdGhTcGVjaWZpZWRGaWVsZHMoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmluc2VydE1hbnkoSW52ZW50b3J5QWRqdXN0bWVudCwgW1xuICAgICAge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ3NvbWV0aGluZyBhJyxcbiAgICAgICAgY3JlYXRlZEF0OiAxLFxuICAgICAgICBpdGVtQWRqdXN0bWVudHM6IFtcbiAgICAgICAgICB7IGJ1eVByaWNlOiAxLCBjcmVhdGVkQXQ6IDEgfSxcbiAgICAgICAgICB7IGJ1eVByaWNlOiAxLCBjcmVhdGVkQXQ6IDEgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnc29tZXRoaW5nIGInLFxuICAgICAgICBjcmVhdGVkQXQ6IDEsXG4gICAgICAgIGl0ZW1BZGp1c3RtZW50czogW1xuICAgICAgICAgIHsgaWQ6IDEsIGJ1eVByaWNlOiAxLCB1cGRhdGVkQXQ6IDEgfSxcbiAgICAgICAgICB7IGJ1eVByaWNlOiAxLCBjcmVhdGVkQXQ6IDEgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgXSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aChcbiAgICAgIDEsXG4gICAgICBcIklOU0VSVCBJTlRPIGBJbnZlbnRvcnlBZGp1c3RtZW50YCAoYGRlc2NyaXB0aW9uYCwgYGNyZWF0ZWRBdGApIFZBTFVFUyAoJ3NvbWV0aGluZyBhJywgMSksICgnc29tZXRoaW5nIGInLCAxKVwiXG4gICAgKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aChcbiAgICAgIDIsXG4gICAgICAnSU5TRVJUIElOVE8gYEl0ZW1BZGp1c3RtZW50YCAoYGJ1eVByaWNlYCwgYGNyZWF0ZWRBdGAsIGBpbnZlbnRvcnlBZGp1c3RtZW50SWRgKSBWQUxVRVMgKDEsIDEsIDEpLCAoMSwgMSwgMSknXG4gICAgKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgzLCAnSU5TRVJUIElOVE8gYEl0ZW1BZGp1c3RtZW50YCAoYGJ1eVByaWNlYCwgYGNyZWF0ZWRBdGAsIGBpbnZlbnRvcnlBZGp1c3RtZW50SWRgKSBWQUxVRVMgKDEsIDEsIDIpJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoXG4gICAgICA0LFxuICAgICAgJ1VQREFURSBgSXRlbUFkanVzdG1lbnRgIFNFVCBgYnV5UHJpY2VgID0gMSwgYHVwZGF0ZWRBdGAgPSAxLCBgaW52ZW50b3J5QWRqdXN0bWVudElkYCA9IDIgV0hFUkUgYGlkYCA9IDEnXG4gICAgKTtcblxuICAgIGF3YWl0IHRoaXMucXVlcmllci5maW5kTWFueShJbnZlbnRvcnlBZGp1c3RtZW50LCB7XG4gICAgICAkcHJvamVjdDogeyBpZDogdHJ1ZSwgaXRlbUFkanVzdG1lbnRzOiBbJ2J1eVByaWNlJ10gfSxcbiAgICAgICRmaWx0ZXI6IHsgY3JlYXRlZEF0OiAxIH0sXG4gICAgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aChcbiAgICAgIDEsXG4gICAgICAnU0VMRUNUIGBJbnZlbnRvcnlBZGp1c3RtZW50YC5gaWRgIEZST00gYEludmVudG9yeUFkanVzdG1lbnRgIFdIRVJFIGBJbnZlbnRvcnlBZGp1c3RtZW50YC5gY3JlYXRlZEF0YCA9IDEnXG4gICAgKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aChcbiAgICAgIDIsXG4gICAgICAnU0VMRUNUIGBidXlQcmljZWAsIGBpbnZlbnRvcnlBZGp1c3RtZW50SWRgIEZST00gYEl0ZW1BZGp1c3RtZW50YCBXSEVSRSBgaW52ZW50b3J5QWRqdXN0bWVudElkYCBJTiAoMSwgMiknXG4gICAgKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcyg0KTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZEZpbmRNYW55QW5kUHJvamVjdE9uZVRvTWFueSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0TWFueShJbnZlbnRvcnlBZGp1c3RtZW50LCBbXG4gICAgICB7IGlkOiAxMjMsIGRlc2NyaXB0aW9uOiAnc29tZXRoaW5nIGEnLCBjcmVhdGVkQXQ6IDEgfSxcbiAgICAgIHsgaWQ6IDQ1NiwgZGVzY3JpcHRpb246ICdzb21ldGhpbmcgYicsIGNyZWF0ZWRBdDogMSB9LFxuICAgIF0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoXG4gICAgICAxLFxuICAgICAgXCJJTlNFUlQgSU5UTyBgSW52ZW50b3J5QWRqdXN0bWVudGAgKGBpZGAsIGBkZXNjcmlwdGlvbmAsIGBjcmVhdGVkQXRgKSBWQUxVRVMgKDEyMywgJ3NvbWV0aGluZyBhJywgMSksICg0NTYsICdzb21ldGhpbmcgYicsIDEpXCJcbiAgICApO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmZpbmRNYW55KEludmVudG9yeUFkanVzdG1lbnQsIHtcbiAgICAgICRwcm9qZWN0OiB7IGlkOiB0cnVlLCBpdGVtQWRqdXN0bWVudHM6IHRydWUgfSxcbiAgICAgICRmaWx0ZXI6IHsgY3JlYXRlZEF0OiAxIH0sXG4gICAgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aChcbiAgICAgIDEsXG4gICAgICAnU0VMRUNUIGBJbnZlbnRvcnlBZGp1c3RtZW50YC5gaWRgIEZST00gYEludmVudG9yeUFkanVzdG1lbnRgIFdIRVJFIGBJbnZlbnRvcnlBZGp1c3RtZW50YC5gY3JlYXRlZEF0YCA9IDEnXG4gICAgKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aChcbiAgICAgIDIsXG4gICAgICAnU0VMRUNUIGBpZGAsIGBjb21wYW55SWRgLCBgY3JlYXRvcklkYCwgYGNyZWF0ZWRBdGAsIGB1cGRhdGVkQXRgLCBgaXRlbUlkYCwgYG51bWJlcmAsIGBidXlQcmljZWAsIGBzdG9yZWhvdXNlSWRgJyArXG4gICAgICAgICcsIGBpbnZlbnRvcnlBZGp1c3RtZW50SWRgIEZST00gYEl0ZW1BZGp1c3RtZW50YCBXSEVSRSBgaW52ZW50b3J5QWRqdXN0bWVudElkYCBJTiAoMTIzLCA0NTYpJ1xuICAgICk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gIH1cblxuICBhc3luYyBzaG91bGRGaW5kT25lQW5kUHJvamVjdE1hbnlUb01hbnkoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmluc2VydE9uZShJdGVtLCB7IGlkOiAxMjMsIGNyZWF0ZWRBdDogMSB9KTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDEsICdJTlNFUlQgSU5UTyBgSXRlbWAgKGBpZGAsIGBjcmVhdGVkQXRgKSBWQUxVRVMgKDEyMywgMSknKTtcblxuICAgIGF3YWl0IHRoaXMucXVlcmllci5maW5kT25lKEl0ZW0sIHtcbiAgICAgICRwcm9qZWN0OiB7IGlkOiB0cnVlLCBjcmVhdGVkQXQ6IHRydWUsIHRhZ3M6IFsnaWQnXSB9LFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMSwgJ1NFTEVDVCBgSXRlbWAuYGlkYCwgYEl0ZW1gLmBjcmVhdGVkQXRgIEZST00gYEl0ZW1gIExJTUlUIDEnKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aChcbiAgICAgIDIsXG4gICAgICAnU0VMRUNUIGBJdGVtVGFnYC5gaWRgLCBgSXRlbVRhZ2AuYGl0ZW1JZGAsIGB0YWdgLmBpZGAgYHRhZy5pZGAnICtcbiAgICAgICAgJyBGUk9NIGBJdGVtVGFnYCBJTk5FUiBKT0lOIGBUYWdgIGB0YWdgIE9OIGB0YWdgLmBpZGAgPSBgSXRlbVRhZ2AuYHRhZ0lkYCcgK1xuICAgICAgICAnIFdIRVJFIGBJdGVtVGFnYC5gaXRlbUlkYCBJTiAoMTIzKSdcbiAgICApO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygyKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDEpO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkRmluZE9uZUJ5SWRBbmRQcm9qZWN0TWFueVRvTWFueSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKEl0ZW0sIHsgaWQ6IDEyMywgY3JlYXRlZEF0OiAxIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgJ0lOU0VSVCBJTlRPIGBJdGVtYCAoYGlkYCwgYGNyZWF0ZWRBdGApIFZBTFVFUyAoMTIzLCAxKScpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmZpbmRPbmVCeUlkKEl0ZW0sIDEyMywge1xuICAgICAgJHByb2plY3Q6IHsgaWQ6IDEsIGNyZWF0ZWRBdDogMSwgdGFnczogWydpZCddIH0sXG4gICAgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aCgxLCAnU0VMRUNUIGBJdGVtYC5gaWRgLCBgSXRlbWAuYGNyZWF0ZWRBdGAgRlJPTSBgSXRlbWAgV0hFUkUgYEl0ZW1gLmBpZGAgPSAxMjMgTElNSVQgMScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKFxuICAgICAgMixcbiAgICAgICdTRUxFQ1QgYEl0ZW1UYWdgLmBpZGAsIGBJdGVtVGFnYC5gaXRlbUlkYCwgYHRhZ2AuYGlkYCBgdGFnLmlkYCcgK1xuICAgICAgICAnIEZST00gYEl0ZW1UYWdgIElOTkVSIEpPSU4gYFRhZ2AgYHRhZ2AgT04gYHRhZ2AuYGlkYCA9IGBJdGVtVGFnYC5gdGFnSWRgJyArXG4gICAgICAgICcgV0hFUkUgYEl0ZW1UYWdgLmBpdGVtSWRgIElOICgxMjMpJ1xuICAgICk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gIH1cblxuICBhc3luYyBzaG91bGRGaW5kTWFueSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuZmluZE1hbnkoVXNlciwge1xuICAgICAgJHByb2plY3Q6IHsgaWQ6IHRydWUsIG5hbWU6IHRydWUgfSxcbiAgICAgICRmaWx0ZXI6IHsgY29tcGFueUlkOiAxMjMgfSxcbiAgICAgICRsaW1pdDogMTAwLFxuICAgIH0pO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDEsICdTRUxFQ1QgYGlkYCwgYG5hbWVgIEZST00gYFVzZXJgIFdIRVJFIGBjb21wYW55SWRgID0gMTIzIExJTUlUIDEwMCcpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZEZpbmRNYW55QW5kQ291bnQoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmZpbmRNYW55QW5kQ291bnQoVXNlciwge1xuICAgICAgJHByb2plY3Q6IHsgaWQ6IHRydWUsIG5hbWU6IHRydWUgfSxcbiAgICAgICRmaWx0ZXI6IHsgY29tcGFueUlkOiAxMjMgfSxcbiAgICAgICRzb3J0OiB7IGNyZWF0ZWRBdDogLTEgfSxcbiAgICAgICRza2lwOiA1MCxcbiAgICAgICRsaW1pdDogMTAwLFxuICAgIH0pO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKFxuICAgICAgMSxcbiAgICAgICdTRUxFQ1QgYGlkYCwgYG5hbWVgIEZST00gYFVzZXJgIFdIRVJFIGBjb21wYW55SWRgID0gMTIzIE9SREVSIEJZIGBjcmVhdGVkQXRgIERFU0MgTElNSVQgMTAwIE9GRlNFVCA1MCdcbiAgICApO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDIsICdTRUxFQ1QgQ09VTlQoKikgYGNvdW50YCBGUk9NIGBVc2VyYCBXSEVSRSBgY29tcGFueUlkYCA9IDEyMycpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZEluc2VydE9uZSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKFVzZXIsIHsgY29tcGFueUlkOiAxMjMsIGNyZWF0ZWRBdDogMSB9KTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnSU5TRVJUIElOVE8gYFVzZXJgIChgY29tcGFueUlkYCwgYGNyZWF0ZWRBdGApIFZBTFVFUyAoMTIzLCAxKScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygxKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZEluc2VydE9uZUFuZENhc2NhZGVPbmVUb09uZSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKFVzZXIsIHtcbiAgICAgIG5hbWU6ICdzb21lIG5hbWUnLFxuICAgICAgY3JlYXRlZEF0OiAxLFxuICAgICAgcHJvZmlsZTogeyBwaWN0dXJlOiAnYWJjJywgY3JlYXRlZEF0OiAxIH0sXG4gICAgfSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgXCJJTlNFUlQgSU5UTyBgVXNlcmAgKGBuYW1lYCwgYGNyZWF0ZWRBdGApIFZBTFVFUyAoJ3NvbWUgbmFtZScsIDEpXCIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDIsIFwiSU5TRVJUIElOVE8gYHVzZXJfcHJvZmlsZWAgKGBpbWFnZWAsIGBjcmVhdGVkQXRgLCBgY3JlYXRvcklkYCkgVkFMVUVTICgnYWJjJywgMSwgMSlcIik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDIpO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkSW5zZXJ0T25lQW5kQ2FzY2FkZU1hbnlUb09uZSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKE1lYXN1cmVVbml0LCB7XG4gICAgICBuYW1lOiAnQ2VudGltZXRlcicsXG4gICAgICBjcmVhdGVkQXQ6IDEyMyxcbiAgICAgIGNhdGVnb3J5OiB7IG5hbWU6ICdNZXRyaWMnLCBjcmVhdGVkQXQ6IDEyMyB9LFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgXCJJTlNFUlQgSU5UTyBgTWVhc3VyZVVuaXRgIChgbmFtZWAsIGBjcmVhdGVkQXRgKSBWQUxVRVMgKCdDZW50aW1ldGVyJywgMTIzKVwiKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgyLCBcIklOU0VSVCBJTlRPIGBNZWFzdXJlVW5pdENhdGVnb3J5YCAoYG5hbWVgLCBgY3JlYXRlZEF0YCkgVkFMVUVTICgnTWV0cmljJywgMTIzKVwiKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aChcbiAgICAgIDMsXG4gICAgICBleHBlY3QudG9NYXRjaCgvXlVQREFURSBgTWVhc3VyZVVuaXRgIFNFVCBgY2F0ZWdvcnlJZGAgPSAxLCBgdXBkYXRlZEF0YCA9IFxcZCsgV0hFUkUgYGlkYCA9IDEgQU5EIGBkZWxldGVkQXRgIElTIE5VTEwkLylcbiAgICApO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygzKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZEluc2VydE9uZUFuZENhc2NhZGVPbmVUb01hbnkoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmluc2VydE9uZShJbnZlbnRvcnlBZGp1c3RtZW50LCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ3NvbWUgZGVzY3JpcHRpb24nLFxuICAgICAgY3JlYXRlZEF0OiAxLFxuICAgICAgaXRlbUFkanVzdG1lbnRzOiBbXG4gICAgICAgIHsgYnV5UHJpY2U6IDUwLCBjcmVhdGVkQXQ6IDEgfSxcbiAgICAgICAgeyBidXlQcmljZTogMzAwLCBjcmVhdGVkQXQ6IDEgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgXCJJTlNFUlQgSU5UTyBgSW52ZW50b3J5QWRqdXN0bWVudGAgKGBkZXNjcmlwdGlvbmAsIGBjcmVhdGVkQXRgKSBWQUxVRVMgKCdzb21lIGRlc2NyaXB0aW9uJywgMSlcIik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoXG4gICAgICAyLFxuICAgICAgJ0lOU0VSVCBJTlRPIGBJdGVtQWRqdXN0bWVudGAgKGBidXlQcmljZWAsIGBjcmVhdGVkQXRgLCBgaW52ZW50b3J5QWRqdXN0bWVudElkYCkgVkFMVUVTICg1MCwgMSwgMSksICgzMDAsIDEsIDEpJ1xuICAgICk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDIpO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkVXBkYXRlTWFueSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIudXBkYXRlTWFueShVc2VyLCB7ICRmaWx0ZXI6IHsgY29tcGFueUlkOiA0IH0gfSwgeyBuYW1lOiAnSG9sYScsIHVwZGF0ZWRBdDogMSB9KTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCBcIlVQREFURSBgVXNlcmAgU0VUIGBuYW1lYCA9ICdIb2xhJywgYHVwZGF0ZWRBdGAgPSAxIFdIRVJFIGBjb21wYW55SWRgID0gNFwiKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDApO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gIH1cblxuICBhc3luYyBzaG91bGRVcGRhdGVPbmVCeUlkKCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci51cGRhdGVPbmVCeUlkKFVzZXIsIDUsIHsgY29tcGFueUlkOiAxMjMsIHVwZGF0ZWRBdDogMSB9KTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnVVBEQVRFIGBVc2VyYCBTRVQgYGNvbXBhbnlJZGAgPSAxMjMsIGB1cGRhdGVkQXRgID0gMSBXSEVSRSBgaWRgID0gNScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygxKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFVwZGF0ZU9uZUJ5SWRBbmRDYXNjYWRlT25lVG9PbmUoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmluc2VydE9uZShVc2VyLCB7IGNyZWF0ZWRBdDogMSB9KTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDEsICdJTlNFUlQgSU5UTyBgVXNlcmAgKGBjcmVhdGVkQXRgKSBWQUxVRVMgKDEpJyk7XG5cbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIudXBkYXRlT25lQnlJZChVc2VyLCAxLCB7XG4gICAgICBuYW1lOiAnc29tZXRoaW5nJyxcbiAgICAgIHVwZGF0ZWRBdDogMSxcbiAgICAgIHByb2ZpbGU6IHsgcGljdHVyZTogJ3h5eicsIGNyZWF0ZWRBdDogMSB9LFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgXCJVUERBVEUgYFVzZXJgIFNFVCBgbmFtZWAgPSAnc29tZXRoaW5nJywgYHVwZGF0ZWRBdGAgPSAxIFdIRVJFIGBpZGAgPSAxXCIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDMsIFwiSU5TRVJUIElOVE8gYHVzZXJfcHJvZmlsZWAgKGBpbWFnZWAsIGBjcmVhdGVkQXRgLCBgY3JlYXRvcklkYCkgVkFMVUVTICgneHl6JywgMSwgMSlcIik7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aCgxLCAnU0VMRUNUIGBpZGAgRlJPTSBgVXNlcmAgV0hFUkUgYGlkYCA9IDEnKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygzKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFVwZGF0ZU9uZUJ5SWRBbmRDYXNjYWRlT25lVG9PbmVOdWxsKCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5pbnNlcnRPbmUoVXNlciwgeyBjcmVhdGVkQXQ6IDEgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnSU5TRVJUIElOVE8gYFVzZXJgIChgY3JlYXRlZEF0YCkgVkFMVUVTICgxKScpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLnVwZGF0ZU9uZUJ5SWQoVXNlciwgMSwge1xuICAgICAgbmFtZTogJ3NvbWV0aGluZycsXG4gICAgICB1cGRhdGVkQXQ6IDEsXG4gICAgICBwcm9maWxlOiBudWxsLFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgXCJVUERBVEUgYFVzZXJgIFNFVCBgbmFtZWAgPSAnc29tZXRoaW5nJywgYHVwZGF0ZWRBdGAgPSAxIFdIRVJFIGBpZGAgPSAxXCIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDEsICdTRUxFQ1QgYGlkYCBGUk9NIGBVc2VyYCBXSEVSRSBgaWRgID0gMScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDIsICdTRUxFQ1QgYHBrYCBgaWRgIEZST00gYHVzZXJfcHJvZmlsZWAgV0hFUkUgYGNyZWF0b3JJZGAgPSAxJyk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gIH1cblxuICBhc3luYyBzaG91bGRVcGRhdGVPbmVCeUlkQW5kQ2FzY2FkZU9uZVRvTWFueSgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKEludmVudG9yeUFkanVzdG1lbnQsIHsgY3JlYXRlZEF0OiAxIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgJ0lOU0VSVCBJTlRPIGBJbnZlbnRvcnlBZGp1c3RtZW50YCAoYGNyZWF0ZWRBdGApIFZBTFVFUyAoMSknKTtcblxuICAgIGF3YWl0IHRoaXMucXVlcmllci51cGRhdGVPbmVCeUlkKEludmVudG9yeUFkanVzdG1lbnQsIDEsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnc29tZSBkZXNjcmlwdGlvbicsXG4gICAgICB1cGRhdGVkQXQ6IDEsXG4gICAgICBpdGVtQWRqdXN0bWVudHM6IFtcbiAgICAgICAgeyBidXlQcmljZTogNTAsIGNyZWF0ZWRBdDogMSB9LFxuICAgICAgICB7IGJ1eVByaWNlOiAzMDAsIGNyZWF0ZWRBdDogMSB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDIsIFwiVVBEQVRFIGBJbnZlbnRvcnlBZGp1c3RtZW50YCBTRVQgYGRlc2NyaXB0aW9uYCA9ICdzb21lIGRlc2NyaXB0aW9uJywgYHVwZGF0ZWRBdGAgPSAxIFdIRVJFIGBpZGAgPSAxXCIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDEsICdTRUxFQ1QgYGlkYCBGUk9NIGBJbnZlbnRvcnlBZGp1c3RtZW50YCBXSEVSRSBgaWRgID0gMScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDIsICdTRUxFQ1QgYGlkYCBGUk9NIGBJdGVtQWRqdXN0bWVudGAgV0hFUkUgYGludmVudG9yeUFkanVzdG1lbnRJZGAgPSAxJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoXG4gICAgICAzLFxuICAgICAgJ0lOU0VSVCBJTlRPIGBJdGVtQWRqdXN0bWVudGAgKGBidXlQcmljZWAsIGBjcmVhdGVkQXRgLCBgaW52ZW50b3J5QWRqdXN0bWVudElkYCkgVkFMVUVTICg1MCwgMSwgMSksICgzMDAsIDEsIDEpJ1xuICAgICk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMyk7XG4gIH1cblxuICBhc3luYyBzaG91bGRVcGRhdGVPbmVCeUlkQW5kQ2FzY2FkZU9uZVRvTWFueU51bGwoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmluc2VydE9uZShJbnZlbnRvcnlBZGp1c3RtZW50LCB7IGNyZWF0ZWRBdDogMSB9KTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDEsICdJTlNFUlQgSU5UTyBgSW52ZW50b3J5QWRqdXN0bWVudGAgKGBjcmVhdGVkQXRgKSBWQUxVRVMgKDEpJyk7XG5cbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIudXBkYXRlT25lQnlJZChJbnZlbnRvcnlBZGp1c3RtZW50LCAxLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ3NvbWUgZGVzY3JpcHRpb24nLFxuICAgICAgdXBkYXRlZEF0OiAxLFxuICAgICAgaXRlbUFkanVzdG1lbnRzOiBudWxsLFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgXCJVUERBVEUgYEludmVudG9yeUFkanVzdG1lbnRgIFNFVCBgZGVzY3JpcHRpb25gID0gJ3NvbWUgZGVzY3JpcHRpb24nLCBgdXBkYXRlZEF0YCA9IDEgV0hFUkUgYGlkYCA9IDFcIik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMSwgJ1NFTEVDVCBgaWRgIEZST00gYEludmVudG9yeUFkanVzdG1lbnRgIFdIRVJFIGBpZGAgPSAxJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMiwgJ1NFTEVDVCBgaWRgIEZST00gYEl0ZW1BZGp1c3RtZW50YCBXSEVSRSBgaW52ZW50b3J5QWRqdXN0bWVudElkYCA9IDEnKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygyKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFVwZGF0ZU1hbnlBbmRDYXNjYWRlT25lVG9NYW55TnVsbCgpIHtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKEludmVudG9yeUFkanVzdG1lbnQsIHsgY29tcGFueUlkOiAxLCBjcmVhdGVkQXQ6IDEgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnSU5TRVJUIElOVE8gYEludmVudG9yeUFkanVzdG1lbnRgIChgY29tcGFueUlkYCwgYGNyZWF0ZWRBdGApIFZBTFVFUyAoMSwgMSknKTtcblxuICAgIGF3YWl0IHRoaXMucXVlcmllci51cGRhdGVNYW55KFxuICAgICAgSW52ZW50b3J5QWRqdXN0bWVudCxcbiAgICAgIHsgJGZpbHRlcjogeyBjb21wYW55SWQ6IDEgfSB9LFxuICAgICAge1xuICAgICAgICBkZXNjcmlwdGlvbjogJ3NvbWUgZGVzY3JpcHRpb24nLFxuICAgICAgICB1cGRhdGVkQXQ6IDEsXG4gICAgICAgIGl0ZW1BZGp1c3RtZW50czogbnVsbCxcbiAgICAgIH1cbiAgICApO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoXG4gICAgICAyLFxuICAgICAgXCJVUERBVEUgYEludmVudG9yeUFkanVzdG1lbnRgIFNFVCBgZGVzY3JpcHRpb25gID0gJ3NvbWUgZGVzY3JpcHRpb24nLCBgdXBkYXRlZEF0YCA9IDEgV0hFUkUgYGNvbXBhbnlJZGAgPSAxXCJcbiAgICApO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDEsICdTRUxFQ1QgYGlkYCBGUk9NIGBJbnZlbnRvcnlBZGp1c3RtZW50YCBXSEVSRSBgY29tcGFueUlkYCA9IDEnKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aCgyLCAnU0VMRUNUIGBpZGAgRlJPTSBgSXRlbUFkanVzdG1lbnRgIFdIRVJFIGBpbnZlbnRvcnlBZGp1c3RtZW50SWRgID0gMScpO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygyKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDIpO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkSW5zZXJ0T25lQW5kQ2FzY2FkZU1hbnlUb01hbnlJbnNlcnRzKCkge1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5pbnNlcnRPbmUoSXRlbSwge1xuICAgICAgbmFtZTogJ2l0ZW0gb25lJyxcbiAgICAgIGNyZWF0ZWRBdDogMSxcbiAgICAgIHRhZ3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICd0YWcgb25lJyxcbiAgICAgICAgICBjcmVhdGVkQXQ6IDEsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAndGFnIHR3bycsXG4gICAgICAgICAgY3JlYXRlZEF0OiAxLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCBcIklOU0VSVCBJTlRPIGBJdGVtYCAoYG5hbWVgLCBgY3JlYXRlZEF0YCkgVkFMVUVTICgnaXRlbSBvbmUnLCAxKVwiKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgyLCBcIklOU0VSVCBJTlRPIGBUYWdgIChgbmFtZWAsIGBjcmVhdGVkQXRgKSBWQUxVRVMgKCd0YWcgb25lJywgMSksICgndGFnIHR3bycsIDEpXCIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDMsICdJTlNFUlQgSU5UTyBgSXRlbVRhZ2AgKGBpdGVtSWRgLCBgdGFnSWRgKSBWQUxVRVMgKDEsIDEpLCAoMSwgMiknKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygzKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFVwZGF0ZUFuZENhc2NhZGVNYW55VG9NYW55SW5zZXJ0cygpIHtcbiAgICBjb25zdCBpZCA9IGF3YWl0IHRoaXMucXVlcmllci5pbnNlcnRPbmUoSXRlbSwgeyBjcmVhdGVkQXQ6IDEgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnSU5TRVJUIElOVE8gYEl0ZW1gIChgY3JlYXRlZEF0YCkgVkFMVUVTICgxKScpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLnVwZGF0ZU9uZUJ5SWQoSXRlbSwgaWQsIHtcbiAgICAgIG5hbWU6ICdpdGVtIG9uZScsXG4gICAgICB1cGRhdGVkQXQ6IDEsXG4gICAgICB0YWdzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAndGFnIG9uZScsXG4gICAgICAgICAgY3JlYXRlZEF0OiAxLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ3RhZyB0d28nLFxuICAgICAgICAgIGNyZWF0ZWRBdDogMSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgyLCBcIlVQREFURSBgSXRlbWAgU0VUIGBuYW1lYCA9ICdpdGVtIG9uZScsIGB1cGRhdGVkQXRgID0gMSBXSEVSRSBgaWRgID0gMVwiKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aCgxLCAnU0VMRUNUIGBpZGAgRlJPTSBgSXRlbWAgV0hFUkUgYGlkYCA9IDEnKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgzLCBcIklOU0VSVCBJTlRPIGBUYWdgIChgbmFtZWAsIGBjcmVhdGVkQXRgKSBWQUxVRVMgKCd0YWcgb25lJywgMSksICgndGFnIHR3bycsIDEpXCIpO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMiwgJ1NFTEVDVCBgaWRgIEZST00gYEl0ZW1UYWdgIFdIRVJFIGBpdGVtSWRgID0gMScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDQsICdJTlNFUlQgSU5UTyBgSXRlbVRhZ2AgKGBpdGVtSWRgLCBgdGFnSWRgKSBWQUxVRVMgKDEsIDEpLCAoMSwgMiknKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcyg0KTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFVwZGF0ZUFuZENhc2NhZGVNYW55VG9NYW55TGlua3MoKSB7XG4gICAgY29uc3QgaWQgPSBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKEl0ZW0sIHsgY3JlYXRlZEF0OiAxIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgJ0lOU0VSVCBJTlRPIGBJdGVtYCAoYGNyZWF0ZWRBdGApIFZBTFVFUyAoMSknKTtcblxuICAgIGF3YWl0IHRoaXMucXVlcmllci51cGRhdGVPbmVCeUlkKEl0ZW0sIGlkLCB7XG4gICAgICBuYW1lOiAnaXRlbSBvbmUnLFxuICAgICAgdGFnczogW3sgaWQ6IDIyIH0sIHsgaWQ6IDMzIH1dLFxuICAgICAgdXBkYXRlZEF0OiAxLFxuICAgIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgXCJVUERBVEUgYEl0ZW1gIFNFVCBgbmFtZWAgPSAnaXRlbSBvbmUnLCBgdXBkYXRlZEF0YCA9IDEgV0hFUkUgYGlkYCA9IDFcIik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMSwgJ1NFTEVDVCBgaWRgIEZST00gYEl0ZW1gIFdIRVJFIGBpZGAgPSAxJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMiwgJ1NFTEVDVCBgaWRgIEZST00gYEl0ZW1UYWdgIFdIRVJFIGBpdGVtSWRgID0gMScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDMsICdJTlNFUlQgSU5UTyBgSXRlbVRhZ2AgKGBpdGVtSWRgLCBgdGFnSWRgKSBWQUxVRVMgKDEsIDIyKSwgKDEsIDMzKScpO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygyKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDMpO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkRGVsZXRlT25lQW5kQ2FzY2FkZU1hbnlUb01hbnlEZWxldGVzKCkge1xuICAgIGF3YWl0IHRoaXMuc2hvdWxkSW5zZXJ0T25lQW5kQ2FzY2FkZU1hbnlUb01hbnlJbnNlcnRzKCk7XG5cbiAgICBqZXN0LmNsZWFyQWxsTW9ja3MoKTtcblxuICAgIGF3YWl0IHRoaXMucXVlcmllci5kZWxldGVPbmVCeUlkKEl0ZW0sIDEpO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMSwgJ1NFTEVDVCBgaWRgIEZST00gYEl0ZW1gIFdIRVJFIGBpZGAgPSAxJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMiwgJ1NFTEVDVCBgaWRgIEZST00gYEl0ZW1UYWdgIFdIRVJFIGBpdGVtSWRgIElOICgxKScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDEsICdERUxFVEUgRlJPTSBgSXRlbWAgV0hFUkUgYGlkYCBJTiAoMSknKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgyLCAnREVMRVRFIEZST00gYEl0ZW1UYWdgIFdIRVJFIGBpZGAgSU4gKDEsIDIpJyk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDIpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gIH1cblxuICBhc3luYyBzaG91bGREZWxldGVPbmVBbmROb0Nhc2NhZGVNYW55VG9NYW55RGVsZXRlcygpIHtcbiAgICBhd2FpdCB0aGlzLnNob3VsZEluc2VydE9uZUFuZENhc2NhZGVNYW55VG9NYW55SW5zZXJ0cygpO1xuXG4gICAgamVzdC5jbGVhckFsbE1vY2tzKCk7XG5cbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuZGVsZXRlT25lQnlJZChUYWcsIDEpO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLm50aENhbGxlZFdpdGgoMSwgJ1NFTEVDVCBgaWRgIEZST00gYFRhZ2AgV0hFUkUgYGlkYCA9IDEnKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCAnREVMRVRFIEZST00gYFRhZ2AgV0hFUkUgYGlkYCBJTiAoMSknKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygxKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZERlbGV0ZU9uZUJ5SWQoKSB7XG4gICAgY29uc3QgaWQgPSBhd2FpdCB0aGlzLnF1ZXJpZXIuaW5zZXJ0T25lKFVzZXIsIHsgY3JlYXRlZEF0OiAxLCBwcm9maWxlOiB7IGNyZWF0ZWRBdDogMSB9IH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgJ0lOU0VSVCBJTlRPIGBVc2VyYCAoYGNyZWF0ZWRBdGApIFZBTFVFUyAoMSknKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgyLCAnSU5TRVJUIElOVE8gYHVzZXJfcHJvZmlsZWAgKGBjcmVhdGVkQXRgLCBgY3JlYXRvcklkYCkgVkFMVUVTICgxLCAxKScpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmRlbGV0ZU9uZUJ5SWQoVXNlciwgaWQpO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMywgJ0RFTEVURSBGUk9NIGBVc2VyYCBXSEVSRSBgaWRgIElOICgxKScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS5udGhDYWxsZWRXaXRoKDQsICdERUxFVEUgRlJPTSBgdXNlcl9wcm9maWxlYCBXSEVSRSBgcGtgIElOICgxKScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDEsICdTRUxFQ1QgYGlkYCBGUk9NIGBVc2VyYCBXSEVSRSBgaWRgID0gMScpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDIsICdTRUxFQ1QgYHBrYCBgaWRgIEZST00gYHVzZXJfcHJvZmlsZWAnKTtcblxuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMik7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcyg0KTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZERlbGV0ZU1hbnkoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmluc2VydE9uZShVc2VyLCB7IGNyZWF0ZWRBdDogMTIzIH0pO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMSwgJ0lOU0VSVCBJTlRPIGBVc2VyYCAoYGNyZWF0ZWRBdGApIFZBTFVFUyAoMTIzKScpO1xuXG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmRlbGV0ZU1hbnkoVXNlciwgeyAkZmlsdGVyOiB7IGNyZWF0ZWRBdDogMTIzIH0gfSk7XG5cbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aCgxLCAnU0VMRUNUIGBpZGAgRlJPTSBgVXNlcmAgV0hFUkUgYGNyZWF0ZWRBdGAgPSAxMjMnKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkubnRoQ2FsbGVkV2l0aCgyLCAnU0VMRUNUIGBwa2AgYGlkYCBGUk9NIGB1c2VyX3Byb2ZpbGVgJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgJ0RFTEVURSBGUk9NIGBVc2VyYCBXSEVSRSBgaWRgIElOICgxKScpO1xuXG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygyKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDIpO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkQ291bnQoKSB7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLmNvdW50KFVzZXIsIHsgJGZpbHRlcjogeyBjb21wYW55SWQ6IDEyMyB9IH0pO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS5udGhDYWxsZWRXaXRoKDEsICdTRUxFQ1QgQ09VTlQoKikgYGNvdW50YCBGUk9NIGBVc2VyYCBXSEVSRSBgY29tcGFueUlkYCA9IDEyMycpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFVzZVRyYW5zYWN0aW9uKCkge1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlRmFsc3koKTtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuYmVnaW5UcmFuc2FjdGlvbigpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkV2l0aCh0aGlzLnF1ZXJpZXIuZGlhbGVjdC5iZWdpblRyYW5zYWN0aW9uQ29tbWFuZCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmUodHJ1ZSk7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLnVwZGF0ZU9uZUJ5SWQoVXNlciwgNSwgeyBuYW1lOiAnSG9sYScsIHVwZGF0ZWRBdDogMSB9KTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmhhc09wZW5UcmFuc2FjdGlvbikudG9CZSh0cnVlKTtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuY29tbWl0VHJhbnNhY3Rpb24oKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCB0aGlzLnF1ZXJpZXIuZGlhbGVjdC5iZWdpblRyYW5zYWN0aW9uQ29tbWFuZCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgXCJVUERBVEUgYFVzZXJgIFNFVCBgbmFtZWAgPSAnSG9sYScsIGB1cGRhdGVkQXRgID0gMSBXSEVSRSBgaWRgID0gNVwiKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgzLCAnQ09NTUlUJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmVGYWxzeSgpO1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5yZWxlYXNlKCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygzKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDApO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlRmFsc3koKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFVzZVRyYW5zYWN0aW9uQ2FsbGJhY2soKSB7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmVGYWxzeSgpO1xuICAgIGF3YWl0IHRoaXMucXVlcmllci50cmFuc2FjdGlvbihhc3luYyAoKSA9PiB7XG4gICAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFdpdGgodGhpcy5xdWVyaWVyLmRpYWxlY3QuYmVnaW5UcmFuc2FjdGlvbkNvbW1hbmQpO1xuICAgICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmUodHJ1ZSk7XG4gICAgICBhd2FpdCB0aGlzLnF1ZXJpZXIudXBkYXRlT25lQnlJZChVc2VyLCA1LCB7IG5hbWU6ICdIb2xhJywgdXBkYXRlZEF0OiAxIH0pO1xuICAgIH0pO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlRmFsc3koKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCB0aGlzLnF1ZXJpZXIuZGlhbGVjdC5iZWdpblRyYW5zYWN0aW9uQ29tbWFuZCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgXCJVUERBVEUgYFVzZXJgIFNFVCBgbmFtZWAgPSAnSG9sYScsIGB1cGRhdGVkQXRgID0gMSBXSEVSRSBgaWRgID0gNVwiKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgzLCAnQ09NTUlUJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygzKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDApO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkVGhyb3dJZlJvbGxiYWNrSWZFcnJvckluQ2FsbGJhY2soKSB7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmVGYWxzeSgpO1xuICAgIGNvbnN0IHByb20gPSB0aGlzLnF1ZXJpZXIudHJhbnNhY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRXaXRoKHRoaXMucXVlcmllci5kaWFsZWN0LmJlZ2luVHJhbnNhY3Rpb25Db21tYW5kKTtcbiAgICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlKHRydWUpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb21lIGVycm9yJyk7XG4gICAgfSk7XG4gICAgYXdhaXQgZXhwZWN0KHByb20pLnJlamVjdHMudG9UaHJvdygnc29tZSBlcnJvcicpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlRmFsc3koKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikubnRoQ2FsbGVkV2l0aCgxLCB0aGlzLnF1ZXJpZXIuZGlhbGVjdC5iZWdpblRyYW5zYWN0aW9uQ29tbWFuZCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLm50aENhbGxlZFdpdGgoMiwgJ1JPTExCQUNLJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygyKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDApO1xuICB9XG5cbiAgYXN5bmMgc2hvdWxkVGhyb3dJZlRyYW5zYWN0aW9uSXNQZW5kaW5nKCkge1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlRmFsc3koKTtcbiAgICBhd2FpdCB0aGlzLnF1ZXJpZXIuYmVnaW5UcmFuc2FjdGlvbigpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlKHRydWUpO1xuICAgIGF3YWl0IGV4cGVjdCh0aGlzLnF1ZXJpZXIuYmVnaW5UcmFuc2FjdGlvbigpKS5yZWplY3RzLnRvVGhyb3coJ3BlbmRpbmcgdHJhbnNhY3Rpb24nKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmhhc09wZW5UcmFuc2FjdGlvbikudG9CZSh0cnVlKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDEpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFRocm93SWZDb21taXRXaXRoTm9QZW5kaW5nVHJhbnNhY3Rpb24oKSB7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmVGYWxzeSgpO1xuICAgIGF3YWl0IGV4cGVjdCh0aGlzLnF1ZXJpZXIuY29tbWl0VHJhbnNhY3Rpb24oKSkucmVqZWN0cy50b1Rocm93KCdwZW5kaW5nIHRyYW5zYWN0aW9uJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmVGYWxzeSgpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIucnVuKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5hbGwpLnRvQmVDYWxsZWRUaW1lcygwKTtcbiAgfVxuXG4gIGFzeW5jIHNob3VsZFRocm93SWZSb2xsYmFja1dpdGhOb1BlbmRpbmdUcmFuc2FjdGlvbigpIHtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmhhc09wZW5UcmFuc2FjdGlvbikudG9CZUZhbHN5KCk7XG4gICAgYXdhaXQgZXhwZWN0KHRoaXMucXVlcmllci5yb2xsYmFja1RyYW5zYWN0aW9uKCkpLnJlamVjdHMudG9UaHJvdygnbm90IGEgcGVuZGluZyB0cmFuc2FjdGlvbicpO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuaGFzT3BlblRyYW5zYWN0aW9uKS50b0JlRmFsc3koKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLnJ1bikudG9CZUNhbGxlZFRpbWVzKDApO1xuICAgIGV4cGVjdCh0aGlzLnF1ZXJpZXIuYWxsKS50b0JlQ2FsbGVkVGltZXMoMCk7XG4gIH1cblxuICBhc3luYyBzaG91bGRUaHJvd0lmUmVsZWFzZVdpdGhQZW5kaW5nVHJhbnNhY3Rpb24oKSB7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmVGYWxzeSgpO1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5iZWdpblRyYW5zYWN0aW9uKCk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmUodHJ1ZSk7XG4gICAgYXdhaXQgdGhpcy5xdWVyaWVyLnVwZGF0ZU9uZUJ5SWQoVXNlciwgNSwgeyBuYW1lOiAnc29tZSBuYW1lJyB9KTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmhhc09wZW5UcmFuc2FjdGlvbikudG9CZSh0cnVlKTtcbiAgICBhd2FpdCBleHBlY3QodGhpcy5xdWVyaWVyLnJlbGVhc2UoKSkucmVqZWN0cy50b1Rocm93KCdwZW5kaW5nIHRyYW5zYWN0aW9uJyk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5oYXNPcGVuVHJhbnNhY3Rpb24pLnRvQmUodHJ1ZSk7XG4gICAgZXhwZWN0KHRoaXMucXVlcmllci5ydW4pLnRvQmVDYWxsZWRUaW1lcygyKTtcbiAgICBleHBlY3QodGhpcy5xdWVyaWVyLmFsbCkudG9CZUNhbGxlZFRpbWVzKDApO1xuICAgIGF3YWl0IHRoaXMucXVlcmllci5yb2xsYmFja1RyYW5zYWN0aW9uKCk7XG4gIH1cbn1cbiJdfQ==
|