appium 2.0.0-beta.20 → 2.0.0-beta.24

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.
Files changed (90) hide show
  1. package/README.md +1 -2
  2. package/build/check-npm-pack-files.js +23 -0
  3. package/build/commands-yml/parse.js +319 -0
  4. package/build/commands-yml/validator.js +130 -0
  5. package/build/index.js +19 -0
  6. package/build/lib/appium.js +22 -7
  7. package/build/lib/cli/args.js +13 -15
  8. package/build/lib/cli/npm.js +27 -16
  9. package/build/lib/cli/parser.js +7 -3
  10. package/build/lib/config.js +27 -47
  11. package/build/lib/extension-config.js +1 -1
  12. package/build/lib/main.js +29 -28
  13. package/build/lib/plugin-config.js +2 -2
  14. package/build/lib/plugins.js +4 -2
  15. package/build/lib/schema/appium-config-schema.js +3 -2
  16. package/build/lib/schema/arg-spec.js +5 -3
  17. package/build/lib/schema/cli-args.js +25 -16
  18. package/build/lib/schema/keywords.js +14 -4
  19. package/build/lib/schema/schema.js +80 -9
  20. package/build/lib/utils.js +16 -36
  21. package/build/postinstall.js +90 -0
  22. package/build/test/cli/cli-e2e-specs.js +221 -0
  23. package/build/test/cli/cli-helpers.js +86 -0
  24. package/build/test/cli/cli-specs.js +71 -0
  25. package/build/test/cli/fixtures/test-driver/package.json +27 -0
  26. package/build/test/cli/schema-args-specs.js +48 -0
  27. package/build/test/cli/schema-e2e-specs.js +47 -0
  28. package/build/test/config-e2e-specs.js +112 -0
  29. package/build/test/config-file-e2e-specs.js +209 -0
  30. package/build/test/config-file-specs.js +281 -0
  31. package/build/test/config-specs.js +246 -0
  32. package/build/test/driver-e2e-specs.js +435 -0
  33. package/build/test/driver-specs.js +386 -0
  34. package/build/test/ext-config-io-specs.js +181 -0
  35. package/build/test/extension-config-specs.js +365 -0
  36. package/build/test/fixtures/allow-feat.txt +5 -0
  37. package/build/test/fixtures/caps.json +3 -0
  38. package/build/test/fixtures/config/allow-insecure.txt +3 -0
  39. package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +5 -0
  40. package/build/test/fixtures/config/appium.config.bad.json +32 -0
  41. package/build/test/fixtures/config/appium.config.ext-good.json +9 -0
  42. package/build/test/fixtures/config/appium.config.ext-unknown-props.json +10 -0
  43. package/build/test/fixtures/config/appium.config.good.js +40 -0
  44. package/build/test/fixtures/config/appium.config.good.json +33 -0
  45. package/build/test/fixtures/config/appium.config.good.yaml +30 -0
  46. package/build/test/fixtures/config/appium.config.invalid.json +31 -0
  47. package/build/test/fixtures/config/appium.config.security-array.json +5 -0
  48. package/build/test/fixtures/config/appium.config.security-delimited.json +5 -0
  49. package/build/test/fixtures/config/appium.config.security-path.json +5 -0
  50. package/build/test/fixtures/config/driver-fake.config.json +8 -0
  51. package/build/test/fixtures/config/nodeconfig.json +3 -0
  52. package/build/test/fixtures/config/plugin-fake.config.json +0 -0
  53. package/build/test/fixtures/default-args.js +35 -0
  54. package/build/test/fixtures/deny-feat.txt +5 -0
  55. package/build/test/fixtures/driver.schema.js +20 -0
  56. package/build/test/fixtures/extensions.yaml +27 -0
  57. package/build/test/fixtures/flattened-schema.js +532 -0
  58. package/build/test/fixtures/plugin.schema.js +20 -0
  59. package/build/test/fixtures/schema-with-extensions.js +28 -0
  60. package/build/test/grid-register-specs.js +74 -0
  61. package/build/test/helpers.js +75 -0
  62. package/build/test/logger-specs.js +76 -0
  63. package/build/test/npm-specs.js +20 -0
  64. package/build/test/parser-specs.js +319 -0
  65. package/build/test/plugin-e2e-specs.js +316 -0
  66. package/build/test/schema/arg-spec-specs.js +70 -0
  67. package/build/test/schema/cli-args-specs.js +408 -0
  68. package/build/test/schema/schema-specs.js +407 -0
  69. package/build/test/utils-specs.js +288 -0
  70. package/index.js +11 -0
  71. package/lib/appium-config.schema.json +2 -1
  72. package/lib/appium.js +51 -8
  73. package/lib/cli/args.js +17 -14
  74. package/lib/cli/npm.js +68 -6
  75. package/lib/cli/parser.js +5 -2
  76. package/lib/config.js +72 -54
  77. package/lib/extension-config.js +1 -1
  78. package/lib/main.js +93 -40
  79. package/lib/plugin-config.js +1 -1
  80. package/lib/plugins.js +2 -0
  81. package/lib/schema/appium-config-schema.js +1 -0
  82. package/lib/schema/arg-spec.js +12 -2
  83. package/lib/schema/cli-args.js +22 -34
  84. package/lib/schema/keywords.js +20 -4
  85. package/lib/schema/schema.js +142 -22
  86. package/lib/utils.js +28 -29
  87. package/package.json +10 -14
  88. package/types/types.d.ts +5 -0
  89. package/build/lib/cli/argparse-actions.js +0 -104
  90. package/lib/cli/argparse-actions.js +0 -77
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ require("source-map-support/register");
6
+
7
+ var _sinon = _interopRequireDefault(require("sinon"));
8
+
9
+ var _parser = _interopRequireDefault(require("../lib/cli/parser"));
10
+
11
+ var _config = require("../lib/config");
12
+
13
+ var _logger = _interopRequireDefault(require("../lib/logger"));
14
+
15
+ var _schema = require("../lib/schema/schema");
16
+
17
+ describe('Config', function () {
18
+ let sandbox;
19
+ beforeEach(function () {
20
+ sandbox = _sinon.default.createSandbox();
21
+ });
22
+ afterEach(function () {
23
+ sandbox.restore();
24
+ });
25
+ describe('Appium config', function () {
26
+ let log;
27
+ let dir;
28
+ beforeEach(function () {
29
+ log = sandbox.spy(console, 'log');
30
+ dir = sandbox.spy(console, 'dir');
31
+ });
32
+ describe('showBuildInfo()', function () {
33
+ it('should log build info to console', async function () {
34
+ const config = (0, _config.getBuildInfo)();
35
+ await (0, _config.showBuildInfo)();
36
+ log.should.have.been.calledOnce;
37
+ log.firstCall.args.should.contain(JSON.stringify(config));
38
+ });
39
+ });
40
+ describe('showConfig', function () {
41
+ describe('when a config file is present', function () {
42
+ it('should dump the current Appium config', function () {
43
+ (0, _config.showConfig)({
44
+ foo: 'bar'
45
+ }, {
46
+ config: {
47
+ server: {
48
+ address: 'quux'
49
+ }
50
+ }
51
+ }, {
52
+ spam: 'food'
53
+ });
54
+ log.should.have.been.calledWith('Appium Configuration\n');
55
+ });
56
+ it('should skip empty objects', function () {
57
+ (0, _config.showConfig)({
58
+ foo: 'bar',
59
+ cows: {},
60
+ pigs: [],
61
+ sheep: 0,
62
+ ducks: false
63
+ }, {
64
+ config: {
65
+ server: {
66
+ address: 'quux'
67
+ }
68
+ }
69
+ }, {
70
+ spam: 'food'
71
+ });
72
+ dir.should.have.been.calledWith({
73
+ foo: 'bar',
74
+ sheep: 0,
75
+ ducks: false
76
+ });
77
+ });
78
+ });
79
+ describe('when a config file is not present', function () {
80
+ it('should dump the current Appium config sans config file contents', function () {
81
+ (0, _config.showConfig)({
82
+ foo: 'bar'
83
+ }, {}, {
84
+ spam: 'food'
85
+ });
86
+ log.should.have.been.calledWith('(no configuration file loaded)\n');
87
+ });
88
+ });
89
+ });
90
+ });
91
+ describe('node.js config', function () {
92
+ let _process = process;
93
+ before(function () {
94
+ process = { ...process
95
+ };
96
+ });
97
+ after(function () {
98
+ process = _process;
99
+ });
100
+ describe('checkNodeOk', function () {
101
+ describe('unsupported nodes', function () {
102
+ const unsupportedVersions = ['v0.1', 'v0.9.12', 'v0.10.36', 'v0.12.14', 'v4.4.7', 'v5.7.0', 'v6.3.1', 'v7.1.1', 'v8.0.0', 'v9.2.3', 'v10.1.0'];
103
+
104
+ for (const version of unsupportedVersions) {
105
+ it(`should fail if node is ${version}`, function () {
106
+ process.version = version;
107
+
108
+ _config.checkNodeOk.should.throw();
109
+ });
110
+ }
111
+ });
112
+ describe('supported nodes', function () {
113
+ it('should succeed if node is 12+', function () {
114
+ process.version = 'v12.0.1';
115
+
116
+ _config.checkNodeOk.should.not.throw();
117
+ });
118
+ it('should succeed if node is 13+', function () {
119
+ process.version = 'v13.6.0';
120
+
121
+ _config.checkNodeOk.should.not.throw();
122
+ });
123
+ it('should succeed if node is 14+', function () {
124
+ process.version = 'v14.0.0';
125
+
126
+ _config.checkNodeOk.should.not.throw();
127
+ });
128
+ });
129
+ });
130
+ describe('warnNodeDeprecations', function () {
131
+ let spy;
132
+ before(function () {
133
+ spy = sandbox.spy(_logger.default, 'warn');
134
+ });
135
+ beforeEach(function () {
136
+ spy.resetHistory();
137
+ });
138
+ it('should not log a warning if node is 8+', function () {
139
+ process.version = 'v8.0.0';
140
+ (0, _config.warnNodeDeprecations)();
141
+
142
+ _logger.default.warn.callCount.should.equal(0);
143
+ });
144
+ it('should not log a warning if node is 9+', function () {
145
+ process.version = 'v9.0.0';
146
+ (0, _config.warnNodeDeprecations)();
147
+
148
+ _logger.default.warn.callCount.should.equal(0);
149
+ });
150
+ });
151
+ });
152
+ describe('server arguments', function () {
153
+ let args;
154
+ describe('getNonDefaultServerArgs', function () {
155
+ describe('without extension schemas', function () {
156
+ beforeEach(async function () {
157
+ await (0, _parser.default)(true);
158
+ args = (0, _schema.getDefaultsForSchema)();
159
+ });
160
+ it('should show none if we have all the defaults', function () {
161
+ let nonDefaultArgs = (0, _config.getNonDefaultServerArgs)(args);
162
+ nonDefaultArgs.should.be.empty;
163
+ });
164
+ it('should catch a non-default argument', function () {
165
+ args.allowCors = true;
166
+ let nonDefaultArgs = (0, _config.getNonDefaultServerArgs)(args);
167
+ nonDefaultArgs.should.eql({
168
+ allowCors: true
169
+ });
170
+ });
171
+ describe('when arg is an array', function () {
172
+ it('should return the arg as an array', function () {
173
+ args.usePlugins = ['all'];
174
+ (0, _config.getNonDefaultServerArgs)(args).should.eql({
175
+ usePlugins: ['all']
176
+ });
177
+ });
178
+ });
179
+ });
180
+ describe('with extension schemas', function () {
181
+ beforeEach(async function () {
182
+ (0, _schema.resetSchema)();
183
+ (0, _schema.registerSchema)('plugin', 'crypto-fiend', {
184
+ type: 'object',
185
+ properties: {
186
+ elite: {
187
+ type: 'boolean',
188
+ default: true
189
+ }
190
+ }
191
+ });
192
+ (0, _schema.finalizeSchema)();
193
+ await (0, _parser.default)(true);
194
+ args = (0, _schema.getDefaultsForSchema)();
195
+ });
196
+ it('should take extension schemas into account', function () {
197
+ const nonDefaultArgs = (0, _config.getNonDefaultServerArgs)(args);
198
+ nonDefaultArgs.should.be.empty;
199
+ });
200
+ it('should catch a non-default argument', function () {
201
+ args['plugin.crypto-fiend.elite'] = false;
202
+ const nonDefaultArgs = (0, _config.getNonDefaultServerArgs)(args);
203
+ nonDefaultArgs.should.eql({
204
+ 'plugin.crypto-fiend.elite': false
205
+ });
206
+ });
207
+ });
208
+ });
209
+ });
210
+ describe('validateTmpDir', function () {
211
+ it('should fail to use a tmp dir with incorrect permissions', function () {
212
+ (0, _config.validateTmpDir)('/private/if_you_run_with_sudo_this_wont_fail').should.be.rejectedWith(/could not ensure/);
213
+ });
214
+ it('should fail to use an undefined tmp dir', function () {
215
+ (0, _config.validateTmpDir)().should.be.rejectedWith(/could not ensure/);
216
+ });
217
+ it('should be able to use a tmp dir with correct permissions', function () {
218
+ (0, _config.validateTmpDir)('/tmp/test_tmp_dir/with/any/number/of/levels').should.not.be.rejected;
219
+ });
220
+ });
221
+ describe('parsing args with empty argv[1]', function () {
222
+ let argv1;
223
+ before(function () {
224
+ argv1 = process.argv[1];
225
+ });
226
+ beforeEach(function () {
227
+ (0, _schema.resetSchema)();
228
+ });
229
+ after(function () {
230
+ process.argv[1] = argv1;
231
+ });
232
+ it('should not fail if process.argv[1] is undefined', async function () {
233
+ delete process.argv[1];
234
+ let args = await (0, _parser.default)();
235
+ args.prog.should.be.equal('appium');
236
+ });
237
+ it('should set "prog" to process.argv[1]', async function () {
238
+ process.argv[1] = 'Hello World';
239
+ let args = await (0, _parser.default)();
240
+ args.prog.should.be.equal('Hello World');
241
+ });
242
+ });
243
+ });require('source-map-support').install();
244
+
245
+
246
+ //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvY29uZmlnLXNwZWNzLmpzIl0sIm5hbWVzIjpbImRlc2NyaWJlIiwic2FuZGJveCIsImJlZm9yZUVhY2giLCJzaW5vbiIsImNyZWF0ZVNhbmRib3giLCJhZnRlckVhY2giLCJyZXN0b3JlIiwibG9nIiwiZGlyIiwic3B5IiwiY29uc29sZSIsIml0IiwiY29uZmlnIiwic2hvdWxkIiwiaGF2ZSIsImJlZW4iLCJjYWxsZWRPbmNlIiwiZmlyc3RDYWxsIiwiYXJncyIsImNvbnRhaW4iLCJKU09OIiwic3RyaW5naWZ5IiwiZm9vIiwic2VydmVyIiwiYWRkcmVzcyIsInNwYW0iLCJjYWxsZWRXaXRoIiwiY293cyIsInBpZ3MiLCJzaGVlcCIsImR1Y2tzIiwiX3Byb2Nlc3MiLCJwcm9jZXNzIiwiYmVmb3JlIiwiYWZ0ZXIiLCJ1bnN1cHBvcnRlZFZlcnNpb25zIiwidmVyc2lvbiIsImNoZWNrTm9kZU9rIiwidGhyb3ciLCJub3QiLCJsb2dnZXIiLCJyZXNldEhpc3RvcnkiLCJ3YXJuIiwiY2FsbENvdW50IiwiZXF1YWwiLCJub25EZWZhdWx0QXJncyIsImJlIiwiZW1wdHkiLCJhbGxvd0NvcnMiLCJlcWwiLCJ1c2VQbHVnaW5zIiwidHlwZSIsInByb3BlcnRpZXMiLCJlbGl0ZSIsImRlZmF1bHQiLCJyZWplY3RlZFdpdGgiLCJyZWplY3RlZCIsImFyZ3YxIiwiYXJndiIsInByb2ciXSwibWFwcGluZ3MiOiI7Ozs7OztBQUdBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUVBQSxRQUFRLENBQUMsUUFBRCxFQUFXLFlBQVk7QUFFN0IsTUFBSUMsT0FBSjtBQUVBQyxFQUFBQSxVQUFVLENBQUMsWUFBWTtBQUNyQkQsSUFBQUEsT0FBTyxHQUFHRSxlQUFNQyxhQUFOLEVBQVY7QUFDRCxHQUZTLENBQVY7QUFJQUMsRUFBQUEsU0FBUyxDQUFDLFlBQVk7QUFDcEJKLElBQUFBLE9BQU8sQ0FBQ0ssT0FBUjtBQUNELEdBRlEsQ0FBVDtBQUlBTixFQUFBQSxRQUFR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akI7QUFDQUEsTUFBQUEsSUFBSSxDQUFDeUMsSUFBTCxDQUFVOUMsTUFBVixDQUFpQmlDLEVBQWpCLENBQW9CRixLQUFwQixDQUEwQixhQUExQjtBQUNELEtBSkMsQ0FBRjtBQUtELEdBMUJPLENBQVI7QUE0QkQsQ0FwTk8sQ0FBUiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG4vLyB0cmFuc3BpbGU6bW9jaGFcbmltcG9ydCBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgZ2V0UGFyc2VyIGZyb20gJy4uL2xpYi9jbGkvcGFyc2VyJztcbmltcG9ydCB7IGNoZWNrTm9kZU9rLCBnZXRCdWlsZEluZm8sIGdldE5vbkRlZmF1bHRTZXJ2ZXJBcmdzLCBzaG93QnVpbGRJbmZvLCBzaG93Q29uZmlnLCB2YWxpZGF0ZVRtcERpciwgd2Fybk5vZGVEZXByZWNhdGlvbnMgfSBmcm9tICcuLi9saWIvY29uZmlnJztcbmltcG9ydCBsb2dnZXIgZnJvbSAnLi4vbGliL2xvZ2dlcic7XG5pbXBvcnQgeyBnZXREZWZhdWx0c0ZvclNjaGVtYSwgcmVzZXRTY2hlbWEsIHJlZ2lzdGVyU2NoZW1hLCBmaW5hbGl6ZVNjaGVtYSB9IGZyb20gJy4uL2xpYi9zY2hlbWEvc2NoZW1hJztcblxuZGVzY3JpYmUoJ0NvbmZpZycsIGZ1bmN0aW9uICgpIHtcbiAgLyoqIEB0eXBlIHtpbXBvcnQoJ3Npbm9uJykuU2lub25TYW5kYm94fSAqL1xuICBsZXQgc2FuZGJveDtcblxuICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICB9KTtcblxuICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3gucmVzdG9yZSgpO1xuICB9KTtcblxuICBkZXNjcmliZSgnQXBwaXVtIGNvbmZpZycsIGZ1bmN0aW9uICgpIHtcbiAgICAvKiogQHR5cGUge2ltcG9ydCgnc2lub24nKS5TaW5vblNweTxbbWVzc2FnZT86IGFueSwgLi4uZXh0cmE6IGFueVtdXSx2b2lkPn0gKi9cbiAgICBsZXQgbG9nO1xuICAgIC8qKiBAdHlwZSB7aW1wb3J0KCdzaW5vbicpLlNpbm9uU3B5PFttZXNzYWdlPzogYW55LCAuLi5leHRyYTogYW55W11dLHZvaWQ+fSAqL1xuICAgIGxldCBkaXI7XG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBsb2cgPSBzYW5kYm94LnNweShjb25zb2xlLCAnbG9nJyk7XG4gICAgICBkaXIgPSBzYW5kYm94LnNweShjb25zb2xlLCAnZGlyJyk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnc2hvd0J1aWxkSW5mbygpJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCBsb2cgYnVpbGQgaW5mbyB0byBjb25zb2xlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjb25maWcgPSBnZXRCdWlsZEluZm8oKTtcbiAgICAgICAgYXdhaXQgc2hvd0J1aWxkSW5mbygpO1xuICAgICAgICBsb2cuc2hvdWxkLmhhdmUuYmVlbi5jYWxsZWRPbmNlO1xuICAgICAgICBsb2cuZmlyc3RDYWxsLmFyZ3Muc2hvdWxkLmNvbnRhaW4oSlNPTi5zdHJpbmdpZnkoY29uZmlnKSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdzaG93Q29uZmlnJywgZnVuY3Rpb24gKCkge1xuICAgICAgZGVzY3JpYmUoJ3doZW4gYSBjb25maWcgZmlsZSBpcyBwcmVzZW50JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBpdCgnc2hvdWxkIGR1bXAgdGhlIGN1cnJlbnQgQXBwaXVtIGNvbmZpZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBzaG93Q29uZmlnKHtmb286ICdiYXInfSwge2NvbmZpZzoge3NlcnZlcjoge2FkZHJlc3M6ICdxdXV4J319fSwge3NwYW06ICdmb29kJ30pO1xuICAgICAgICAgIGxvZy5zaG91bGQuaGF2ZS5iZWVuLmNhbGxlZFdpdGgoJ0FwcGl1bSBDb25maWd1cmF0aW9uXFxuJyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgc2tpcCBlbXB0eSBvYmplY3RzJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHNob3dDb25maWcoe2ZvbzogJ2JhcicsIGNvd3M6IHt9LCBwaWdzOiBbXSwgc2hlZXA6IDAsIGR1Y2tzOiBmYWxzZX0sIHtjb25maWc6IHtzZXJ2ZXI6IHthZGRyZXNzOiAncXV1eCd9fX0sIHtzcGFtOiAnZm9vZCd9KTtcbiAgICAgICAgICBkaXIuc2hvdWxkLmhhdmUuYmVlbi5jYWxsZWRXaXRoKHtmb286ICdiYXInLCBzaGVlcDogMCwgZHVja3M6IGZhbHNlfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd3aGVuIGEgY29uZmlnIGZpbGUgaXMgbm90IHByZXNlbnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgZHVtcCB0aGUgY3VycmVudCBBcHBpdW0gY29uZmlnIHNhbnMgY29uZmlnIGZpbGUgY29udGVudHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgc2hvd0NvbmZpZyh7Zm9vOiAnYmFyJ30sIHt9LCB7c3BhbTogJ2Zvb2QnfSk7XG4gICAgICAgICAgbG9nLnNob3VsZC5oYXZlLmJlZW4uY2FsbGVkV2l0aCgnKG5vIGNvbmZpZ3VyYXRpb24gZmlsZSBsb2FkZWQpXFxuJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdub2RlLmpzIGNvbmZpZycsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgX3Byb2Nlc3MgPSBwcm9jZXNzO1xuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBuZWVkIHRvIGJlIGFibGUgdG8gd3JpdGUgdG8gcHJvY2Vzcy52ZXJzaW9uXG4gICAgICAvLyBidXQgYWxzbyB0byBoYXZlIGFjY2VzcyB0byBwcm9jZXNzIG1ldGhvZHNcbiAgICAgIC8vIHNvIGNvcHkgdGhlbSBvdmVyIHRvIGEgd3JpdGFibGUgb2JqZWN0XG4gICAgICBwcm9jZXNzID0gey4uLnByb2Nlc3N9OyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWdsb2JhbC1hc3NpZ25cbiAgICB9KTtcbiAgICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgICBwcm9jZXNzID0gX3Byb2Nlc3M7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tZ2xvYmFsLWFzc2lnblxuICAgIH0pO1xuICAgIGRlc2NyaWJlKCdjaGVja05vZGVPaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGRlc2NyaWJlKCd1bnN1cHBvcnRlZCBub2RlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgdW5zdXBwb3J0ZWRWZXJzaW9ucyA9IFtcbiAgICAgICAgICAndjAuMScsICd2MC45LjEyJywgJ3YwLjEwLjM2JywgJ3YwLjEyLjE0JyxcbiAgICAgICAgICAndjQuNC43JywgJ3Y1LjcuMCcsICd2Ni4zLjEnLCAndjcuMS4xJyxcbiAgICAgICAgICAndjguMC4wJywgJ3Y5LjIuMycsICd2MTAuMS4wJyxcbiAgICAgICAgXTtcbiAgICAgICAgZm9yIChjb25zdCB2ZXJzaW9uIG9mIHVuc3VwcG9ydGVkVmVyc2lvbnMpIHtcbiAgICAgICAgICBpdChgc2hvdWxkIGZhaWwgaWYgbm9kZSBpcyAke3ZlcnNpb259YCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgcHJvY2Vzcy52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIGNoZWNrTm9kZU9rLnNob3VsZC50aHJvdygpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ3N1cHBvcnRlZCBub2RlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXQoJ3Nob3VsZCBzdWNjZWVkIGlmIG5vZGUgaXMgMTIrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICBwcm9jZXNzLnZlcnNpb24gPSAndjEyLjAuMSc7XG4gICAgICAgICAgY2hlY2tOb2RlT2suc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgICB9KTtcbiAgICAgICAgaXQoJ3Nob3VsZCBzdWNjZWVkIGlmIG5vZGUgaXMgMTMrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICBwcm9jZXNzLnZlcnNpb24gPSAndjEzLjYuMCc7XG4gICAgICAgICAgY2hlY2tOb2RlT2suc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgICB9KTtcbiAgICAgICAgaXQoJ3Nob3VsZCBzdWNjZWVkIGlmIG5vZGUgaXMgMTQrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICBwcm9jZXNzLnZlcnNpb24gPSAndjE0LjAuMCc7XG4gICAgICAgICAgY2hlY2tOb2RlT2suc2hvdWxkLm5vdC50aHJvdygpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3dhcm5Ob2RlRGVwcmVjYXRpb25zJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IHNweTtcbiAgICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNweSA9IHNhbmRib3guc3B5KGxvZ2dlciwgJ3dhcm4nKTtcbiAgICAgIH0pO1xuICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNweS5yZXNldEhpc3RvcnkoKTtcbiAgICAgIH0pO1xuICAgICAgaXQoJ3Nob3VsZCBub3QgbG9nIGEgd2FybmluZyBpZiBub2RlIGlzIDgrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgIHByb2Nlc3MudmVyc2lvbiA9ICd2OC4wLjAnO1xuICAgICAgICB3YXJuTm9kZURlcHJlY2F0aW9ucygpO1xuICAgICAgICBsb2dnZXIud2Fybi5jYWxsQ291bnQuc2hvdWxkLmVxdWFsKDApO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIG5vdCBsb2cgYSB3YXJuaW5nIGlmIG5vZGUgaXMgOSsnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgcHJvY2Vzcy52ZXJzaW9uID0gJ3Y5LjAuMCc7XG4gICAgICAgIHdhcm5Ob2RlRGVwcmVjYXRpb25zKCk7XG4gICAgICAgIGxvZ2dlci53YXJuLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3NlcnZlciBhcmd1bWVudHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGFyZ3M7XG5cbiAgICBkZXNjcmliZSgnZ2V0Tm9uRGVmYXVsdFNlcnZlckFyZ3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBkZXNjcmliZSgnd2l0aG91dCBleHRlbnNpb24gc2NoZW1hcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgZ2V0UGFyc2VyKHRydWUpO1xuICAgICAgICAgIC8vIGdldCBhbGwgdGhlIGRlZmF1bHRzXG4gICAgICAgICAgYXJncyA9IGdldERlZmF1bHRzRm9yU2NoZW1hKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpdCgnc2hvdWxkIHNob3cgbm9uZSBpZiB3ZSBoYXZlIGFsbCB0aGUgZGVmYXVsdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgbGV0IG5vbkRlZmF1bHRBcmdzID0gZ2V0Tm9uRGVmYXVsdFNlcnZlckFyZ3MoYXJncyk7XG4gICAgICAgICAgbm9uRGVmYXVsdEFyZ3Muc2hvdWxkLmJlLmVtcHR5O1xuICAgICAgICB9KTtcbiAgICAgICAgaXQoJ3Nob3VsZCBjYXRjaCBhIG5vbi1kZWZhdWx0IGFyZ3VtZW50JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGFyZ3MuYWxsb3dDb3JzID0gdHJ1ZTtcbiAgICAgICAgICBsZXQgbm9uRGVmYXVsdEFyZ3MgPSBnZXROb25EZWZhdWx0U2VydmVyQXJncyhhcmdzKTtcbiAgICAgICAgICBub25EZWZhdWx0QXJncy5zaG91bGQuZXFsKHthbGxvd0NvcnM6IHRydWV9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGRlc2NyaWJlKCd3aGVuIGFyZyBpcyBhbiBhcnJheScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpdCgnc2hvdWxkIHJldHVybiB0aGUgYXJnIGFzIGFuIGFycmF5JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgYXJncy51c2VQbHVnaW5zID0gWydhbGwnXTtcbiAgICAgICAgICAgIGdldE5vbkRlZmF1bHRTZXJ2ZXJBcmdzKGFyZ3MpLnNob3VsZC5lcWwoe3VzZVBsdWdpbnM6IFsnYWxsJ119KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIGRlc2NyaWJlKCd3aXRoIGV4dGVuc2lvbiBzY2hlbWFzJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXNldFNjaGVtYSgpO1xuICAgICAgICAgIHJlZ2lzdGVyU2NoZW1hKCdwbHVnaW4nLCAnY3J5cHRvLWZpZW5kJywge3R5cGU6ICdvYmplY3QnLCBwcm9wZXJ0aWVzOiB7ZWxpdGU6IHt0eXBlOiAnYm9vbGVhbicsIGRlZmF1bHQ6IHRydWV9fX0pO1xuICAgICAgICAgIGZpbmFsaXplU2NoZW1hKCk7XG4gICAgICAgICAgYXdhaXQgZ2V0UGFyc2VyKHRydWUpO1xuICAgICAgICAgIGFyZ3MgPSBnZXREZWZhdWx0c0ZvclNjaGVtYSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIHRha2UgZXh0ZW5zaW9uIHNjaGVtYXMgaW50byBhY2NvdW50JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IG5vbkRlZmF1bHRBcmdzID0gZ2V0Tm9uRGVmYXVsdFNlcnZlckFyZ3MoYXJncyk7XG4gICAgICAgICAgbm9uRGVmYXVsdEFyZ3Muc2hvdWxkLmJlLmVtcHR5O1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIGNhdGNoIGEgbm9uLWRlZmF1bHQgYXJndW1lbnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXJnc1sncGx1Z2luLmNyeXB0by1maWVuZC5lbGl0ZSddID0gZmFsc2U7XG4gICAgICAgICAgY29uc3Qgbm9uRGVmYXVsdEFyZ3MgPSBnZXROb25EZWZhdWx0U2VydmVyQXJncyhhcmdzKTtcbiAgICAgICAgICBub25EZWZhdWx0QXJncy5zaG91bGQuZXFsKHsncGx1Z2luLmNyeXB0by1maWVuZC5lbGl0ZSc6IGZhbHNlfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2YWxpZGF0ZVRtcERpcicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdXNlIGEgdG1wIGRpciB3aXRoIGluY29ycmVjdCBwZXJtaXNzaW9ucycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhbGlkYXRlVG1wRGlyKCcvcHJpdmF0ZS9pZl95b3VfcnVuX3dpdGhfc3Vkb190aGlzX3dvbnRfZmFpbCcpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2NvdWxkIG5vdCBlbnN1cmUvKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdXNlIGFuIHVuZGVmaW5lZCB0bXAgZGlyJywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgdmFsaWRhdGVUbXBEaXIoKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9jb3VsZCBub3QgZW5zdXJlLyk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBiZSBhYmxlIHRvIHVzZSBhIHRtcCBkaXIgd2l0aCBjb3JyZWN0IHBlcm1pc3Npb25zJywgZnVuY3Rpb24gKCkge1xuICAgICAgdmFsaWRhdGVUbXBEaXIoJy90bXAvdGVzdF90bXBfZGlyL3dpdGgvYW55L251bWJlci9vZi9sZXZlbHMnKS5zaG91bGQubm90LmJlLnJlamVjdGVkO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncGFyc2luZyBhcmdzIHdpdGggZW1wdHkgYXJndlsxXScsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgYXJndjE7XG5cbiAgICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgICAgYXJndjEgPSBwcm9jZXNzLmFyZ3ZbMV07XG4gICAgfSk7XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJlc2V0U2NoZW1hKCk7XG4gICAgfSk7XG5cbiAgICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgICBwcm9jZXNzLmFyZ3ZbMV0gPSBhcmd2MTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IGZhaWwgaWYgcHJvY2Vzcy5hcmd2WzFdIGlzIHVuZGVmaW5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmFyZ3ZbMV07XG4gICAgICBsZXQgYXJncyA9IGF3YWl0IGdldFBhcnNlcigpO1xuICAgICAgYXJncy5wcm9nLnNob3VsZC5iZS5lcXVhbCgnYXBwaXVtJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNldCBcInByb2dcIiB0byBwcm9jZXNzLmFyZ3ZbMV0nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBwcm9jZXNzLmFyZ3ZbMV0gPSAnSGVsbG8gV29ybGQnO1xuICAgICAgbGV0IGFyZ3MgPSBhd2FpdCBnZXRQYXJzZXIoKTtcbiAgICAgIGFyZ3MucHJvZy5zaG91bGQuYmUuZXF1YWwoJ0hlbGxvIFdvcmxkJyk7XG4gICAgfSk7XG4gIH0pO1xuXG59KTtcbiJdLCJmaWxlIjoidGVzdC9jb25maWctc3BlY3MuanMiLCJzb3VyY2VSb290IjoiLi4vLi4ifQ==