UNPKG

36 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright 2019 Google LLC. All Rights Reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * =============================================================================
16 */
17import * as tf from './index';
18import { ALL_ENVS, describeWithFlags, NODE_ENVS } from './jasmine_util';
19import { expectArraysClose } from './test_util';
20describe('deprecation warnings', () => {
21 beforeEach(() => {
22 spyOn(console, 'warn').and.callFake((msg) => null);
23 });
24 it('deprecationWarn warns', () => {
25 // flags_test.ts verifies deprecation warnings are on by default.
26 const deprecationVal = tf.env().get('DEPRECATION_WARNINGS_ENABLED');
27 tf.env().set('DEPRECATION_WARNINGS_ENABLED', true);
28 tf.deprecationWarn('xyz is deprecated.');
29 tf.env().set('DEPRECATION_WARNINGS_ENABLED', deprecationVal);
30 expect(console.warn).toHaveBeenCalledTimes(1);
31 expect(console.warn)
32 .toHaveBeenCalledWith('xyz is deprecated. You can disable deprecation warnings with ' +
33 'tf.disableDeprecationWarnings().');
34 });
35 it('disableDeprecationWarnings called, deprecationWarn doesnt warn', () => {
36 tf.disableDeprecationWarnings();
37 expect(console.warn).toHaveBeenCalledTimes(1);
38 expect(console.warn)
39 .toHaveBeenCalledWith('TensorFlow.js deprecation warnings have been disabled.');
40 // deprecationWarn no longer warns.
41 tf.deprecationWarn('xyz is deprecated.');
42 expect(console.warn).toHaveBeenCalledTimes(1);
43 });
44});
45describe('Flag flipping methods', () => {
46 beforeEach(() => {
47 tf.env().reset();
48 });
49 afterEach(() => {
50 tf.env().reset();
51 });
52 it('tf.enableProdMode', () => {
53 tf.enableProdMode();
54 expect(tf.env().getBool('PROD')).toBe(true);
55 });
56 it('tf.enableDebugMode', () => {
57 // Silence debug warnings.
58 spyOn(console, 'warn');
59 tf.enableDebugMode();
60 expect(tf.env().getBool('DEBUG')).toBe(true);
61 });
62});
63describeWithFlags('time cpu', NODE_ENVS, () => {
64 it('simple upload', async () => {
65 const a = tf.zeros([10, 10]);
66 const time = await tf.time(() => a.square());
67 expect(time.kernelMs > 0);
68 expect(time.wallMs >= time.kernelMs);
69 });
70});
71describeWithFlags('tidy', ALL_ENVS, () => {
72 it('returns Tensor', async () => {
73 tf.tidy(() => {
74 const a = tf.tensor1d([1, 2, 3]);
75 let b = tf.tensor1d([0, 0, 0]);
76 expect(tf.memory().numTensors).toBe(2);
77 tf.tidy(() => {
78 const result = tf.tidy(() => {
79 b = tf.add(a, b);
80 b = tf.add(a, b);
81 b = tf.add(a, b);
82 return tf.add(a, b);
83 });
84 // result is new. All intermediates should be disposed.
85 expect(tf.memory().numTensors).toBe(2 + 1);
86 expect(result.shape).toEqual([3]);
87 expect(result.isDisposed).toBe(false);
88 });
89 // a, b are still here, result should be disposed.
90 expect(tf.memory().numTensors).toBe(2);
91 });
92 expect(tf.memory().numTensors).toBe(0);
93 });
94 it('multiple disposes does not affect num arrays', () => {
95 expect(tf.memory().numTensors).toBe(0);
96 const a = tf.tensor1d([1, 2, 3]);
97 const b = tf.tensor1d([1, 2, 3]);
98 expect(tf.memory().numTensors).toBe(2);
99 a.dispose();
100 a.dispose();
101 expect(tf.memory().numTensors).toBe(1);
102 b.dispose();
103 expect(tf.memory().numTensors).toBe(0);
104 });
105 it('allows primitive types', () => {
106 const a = tf.tidy(() => 5);
107 expect(a).toBe(5);
108 const b = tf.tidy(() => 'hello');
109 expect(b).toBe('hello');
110 });
111 it('allows complex types', async () => {
112 const res = tf.tidy(() => {
113 return { a: tf.scalar(1), b: 'hello', c: [tf.scalar(2), 'world'] };
114 });
115 expectArraysClose(await res.a.data(), [1]);
116 expectArraysClose(await res.c[0].data(), [2]);
117 });
118 it('returns Tensor[]', async () => {
119 const a = tf.tensor1d([1, 2, 3]);
120 const b = tf.tensor1d([0, -1, 1]);
121 expect(tf.memory().numTensors).toBe(2);
122 tf.tidy(() => {
123 const result = tf.tidy(() => {
124 tf.add(a, b);
125 return [tf.add(a, b), tf.sub(a, b)];
126 });
127 // the 2 results are new. All intermediates should be disposed.
128 expect(tf.memory().numTensors).toBe(4);
129 expect(result[0].isDisposed).toBe(false);
130 expect(result[0].shape).toEqual([3]);
131 expect(result[1].isDisposed).toBe(false);
132 expect(result[1].shape).toEqual([3]);
133 expect(tf.memory().numTensors).toBe(4);
134 });
135 // the 2 results should be disposed.
136 expect(tf.memory().numTensors).toBe(2);
137 a.dispose();
138 b.dispose();
139 expect(tf.memory().numTensors).toBe(0);
140 });
141 it('basic usage without return', () => {
142 const a = tf.tensor1d([1, 2, 3]);
143 let b = tf.tensor1d([0, 0, 0]);
144 expect(tf.memory().numTensors).toBe(2);
145 tf.tidy(() => {
146 b = tf.add(a, b);
147 b = tf.add(a, b);
148 b = tf.add(a, b);
149 tf.add(a, b);
150 });
151 // all intermediates should be disposed.
152 expect(tf.memory().numTensors).toBe(2);
153 });
154 it('nested usage', async () => {
155 const a = tf.tensor1d([1, 2, 3]);
156 let b = tf.tensor1d([0, 0, 0]);
157 expect(tf.memory().numTensors).toBe(2);
158 tf.tidy(() => {
159 const result = tf.tidy(() => {
160 b = tf.add(a, b);
161 b = tf.tidy(() => {
162 b = tf.tidy(() => {
163 return tf.add(a, b);
164 });
165 // original a, b, and two intermediates.
166 expect(tf.memory().numTensors).toBe(4);
167 tf.tidy(() => {
168 tf.add(a, b);
169 });
170 // All the intermediates should be cleaned up.
171 expect(tf.memory().numTensors).toBe(4);
172 return tf.add(a, b);
173 });
174 expect(tf.memory().numTensors).toBe(4);
175 return tf.add(a, b);
176 });
177 expect(tf.memory().numTensors).toBe(3);
178 expect(result.isDisposed).toBe(false);
179 expect(result.shape).toEqual([3]);
180 });
181 expect(tf.memory().numTensors).toBe(2);
182 });
183 it('nested usage returns tensor created from outside scope', () => {
184 const x = tf.scalar(1);
185 tf.tidy(() => {
186 tf.tidy(() => {
187 return x;
188 });
189 });
190 expect(x.isDisposed).toBe(false);
191 });
192 it('nested usage with keep works', () => {
193 let b;
194 tf.tidy(() => {
195 const a = tf.scalar(1);
196 tf.tidy(() => {
197 b = tf.keep(a);
198 });
199 });
200 expect(b.isDisposed).toBe(false);
201 b.dispose();
202 });
203 it('single argument', () => {
204 let hasRan = false;
205 tf.tidy(() => {
206 hasRan = true;
207 });
208 expect(hasRan).toBe(true);
209 });
210 it('single argument, but not a function throws error', () => {
211 expect(() => {
212 tf.tidy('asdf');
213 }).toThrowError();
214 });
215 it('2 arguments, first is string', () => {
216 let hasRan = false;
217 tf.tidy('name', () => {
218 hasRan = true;
219 });
220 expect(hasRan).toBe(true);
221 });
222 it('2 arguments, but first is not string throws error', () => {
223 expect(() => {
224 // tslint:disable-next-line:no-any
225 tf.tidy(4, () => { });
226 }).toThrowError();
227 });
228 it('2 arguments, but second is not a function throws error', () => {
229 expect(() => {
230 // tslint:disable-next-line:no-any
231 tf.tidy('name', 'another name');
232 }).toThrowError();
233 });
234 it('works with arbitrary depth of result', async () => {
235 tf.tidy(() => {
236 const res = tf.tidy(() => {
237 return [tf.scalar(1), [[tf.scalar(2)]], { list: [tf.scalar(3)] }];
238 });
239 expect(res[0].isDisposed).toBe(false);
240 // tslint:disable-next-line:no-any
241 expect(res[1][0][0].isDisposed).toBe(false);
242 // tslint:disable-next-line:no-any
243 expect(res[2].list[0].isDisposed).toBe(false);
244 expect(tf.memory().numTensors).toBe(3);
245 return res[0];
246 });
247 // Everything but scalar(1) got disposed.
248 expect(tf.memory().numTensors).toBe(1);
249 });
250});
251//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2xvYmFsc190ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9nbG9iYWxzX3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RSxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFFOUMsUUFBUSxDQUFDLHNCQUFzQixFQUFFLEdBQUcsRUFBRTtJQUNwQyxVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2QsS0FBSyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBVyxFQUFRLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuRSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyx1QkFBdUIsRUFBRSxHQUFHLEVBQUU7UUFDL0IsaUVBQWlFO1FBQ2pFLE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUNwRSxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLDhCQUE4QixFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ25ELEVBQUUsQ0FBQyxlQUFlLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUN6QyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLDhCQUE4QixFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQzdELE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7YUFDZixv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Q0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNyRCxrQ0FBa0M7WUFDbEMsTUFBTSxDQUFFLEdBQUcsQ0FBQyxDQUFDLENBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZELE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3ZDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hCLENBQUMsQ0FBQyxDQUFDO1FBQ0gseUNBQXlDO1FBQ3pDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCAqIGFzIHRmIGZyb20gJy4vaW5kZXgnO1xuaW1wb3J0IHtBTExfRU5WUywgZGVzY3JpYmVXaXRoRmxhZ3MsIE5PREVfRU5WU30gZnJvbSAnLi9qYXNtaW5lX3V0aWwnO1xuaW1wb3J0IHtleHBlY3RBcnJheXNDbG9zZX0gZnJvbSAnLi90ZXN0X3V0aWwnO1xuXG5kZXNjcmliZSgnZGVwcmVjYXRpb24gd2FybmluZ3MnLCAoKSA9PiB7XG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIHNweU9uKGNvbnNvbGUsICd3YXJuJykuYW5kLmNhbGxGYWtlKChtc2c6IHN0cmluZyk6IHZvaWQgPT4gbnVsbCk7XG4gIH0pO1xuXG4gIGl0KCdkZXByZWNhdGlvbldhcm4gd2FybnMnLCAoKSA9PiB7XG4gICAgLy8gZmxhZ3NfdGVzdC50cyB2ZXJpZmllcyBkZXByZWNhdGlvbiB3YXJuaW5ncyBhcmUgb24gYnkgZGVmYXVsdC5cbiAgICBjb25zdCBkZXByZWNhdGlvblZhbCA9IHRmLmVudigpLmdldCgnREVQUkVDQVRJT05fV0FSTklOR1NfRU5BQkxFRCcpO1xuICAgIHRmLmVudigpLnNldCgnREVQUkVDQVRJT05fV0FSTklOR1NfRU5BQkxFRCcsIHRydWUpO1xuICAgIHRmLmRlcHJlY2F0aW9uV2FybigneHl6IGlzIGRlcHJlY2F0ZWQuJyk7XG4gICAgdGYuZW52KCkuc2V0KCdERVBSRUNBVElPTl9XQVJOSU5HU19FTkFCTEVEJywgZGVwcmVjYXRpb25WYWwpO1xuICAgIGV4cGVjdChjb25zb2xlLndhcm4pLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcygxKTtcbiAgICBleHBlY3QoY29uc29sZS53YXJuKVxuICAgICAgICAudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgICAgICAneHl6IGlzIGRlcHJlY2F0ZWQuIFlvdSBjYW4gZGlzYWJsZSBkZXByZWNhdGlvbiB3YXJuaW5ncyB3aXRoICcgK1xuICAgICAgICAgICAgJ3RmLmRpc2FibGVEZXByZWNhdGlvbldhcm5pbmdzKCkuJyk7XG4gIH0pO1xuXG4gIGl0KCdkaXNhYmxlRGVwcmVjYXRpb25XYXJuaW5ncyBjYWxsZWQsIGRlcHJlY2F0aW9uV2FybiBkb2VzbnQgd2FybicsICgpID0+IHtcbiAgICB0Zi5kaXNhYmxlRGVwcmVjYXRpb25XYXJuaW5ncygpO1xuICAgIGV4cGVjdChjb25zb2xlLndhcm4pLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcygxKTtcbiAgICBleHBlY3QoY29uc29sZS53YXJuKVxuICAgICAgICAudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgICAgICAnVGVuc29yRmxvdy5qcyBkZXByZWNhdGlvbiB3YXJuaW5ncyBoYXZlIGJlZW4gZGlzYWJsZWQuJyk7XG5cbiAgICAvLyBkZXByZWNhdGlvbldhcm4gbm8gbG9uZ2VyIHdhcm5zLlxuICAgIHRmLmRlcHJlY2F0aW9uV2FybigneHl6IGlzIGRlcHJlY2F0ZWQuJyk7XG4gICAgZXhwZWN0KGNvbnNvbGUud2FybikudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDEpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnRmxhZyBmbGlwcGluZyBtZXRob2RzJywgKCkgPT4ge1xuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICB0Zi5lbnYoKS5yZXNldCgpO1xuICB9KTtcblxuICBhZnRlckVhY2goKCkgPT4ge1xuICAgIHRmLmVudigpLnJlc2V0KCk7XG4gIH0pO1xuXG4gIGl0KCd0Zi5lbmFibGVQcm9kTW9kZScsICgpID0+IHtcbiAgICB0Zi5lbmFibGVQcm9kTW9kZSgpO1xuICAgIGV4cGVjdCh0Zi5lbnYoKS5nZXRCb29sKCdQUk9EJykpLnRvQmUodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCd0Zi5lbmFibGVEZWJ1Z01vZGUnLCAoKSA9PiB7XG4gICAgLy8gU2lsZW5jZSBkZWJ1ZyB3YXJuaW5ncy5cbiAgICBzcHlPbihjb25zb2xlLCAnd2FybicpO1xuICAgIHRmLmVuYWJsZURlYnVnTW9kZSgpO1xuICAgIGV4cGVjdCh0Zi5lbnYoKS5nZXRCb29sKCdERUJVRycpKS50b0JlKHRydWUpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZVdpdGhGbGFncygndGltZSBjcHUnLCBOT0RFX0VOVlMsICgpID0+IHtcbiAgaXQoJ3NpbXBsZSB1cGxvYWQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYSA9IHRmLnplcm9zKFsxMCwgMTBdKTtcbiAgICBjb25zdCB0aW1lID0gYXdhaXQgdGYudGltZSgoKSA9PiBhLnNxdWFyZSgpKTtcbiAgICBleHBlY3QodGltZS5rZXJuZWxNcyA+IDApO1xuICAgIGV4cGVjdCh0aW1lLndhbGxNcyA+PSB0aW1lLmtlcm5lbE1zKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmVXaXRoRmxhZ3MoJ3RpZHknLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgncmV0dXJucyBUZW5zb3InLCBhc3luYyAoKSA9PiB7XG4gICAgdGYudGlkeSgoKSA9PiB7XG4gICAgICBjb25zdCBhID0gdGYudGVuc29yMWQoWzEsIDIsIDNdKTtcbiAgICAgIGxldCBiID0gdGYudGVuc29yMWQoWzAsIDAsIDBdKTtcblxuICAgICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoMik7XG4gICAgICB0Zi50aWR5KCgpID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGYudGlkeSgoKSA9PiB7XG4gICAgICAgICAgYiA9IHRmLmFkZChhLCBiKTtcbiAgICAgICAgICBiID0gdGYuYWRkKGEsIGIpO1xuICAgICAgICAgIGIgPSB0Zi5hZGQoYSwgYik7XG4gICAgICAgICAgcmV0dXJuIHRmLmFkZChhLCBiKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gcmVzdWx0IGlzIG5ldy4gQWxsIGludGVybWVkaWF0ZXMgc2hvdWxkIGJlIGRpc3Bvc2VkLlxuICAgICAgICBleHBlY3QodGYubWVtb3J5KCkubnVtVGVuc29ycykudG9CZSgyICsgMSk7XG4gICAgICAgIGV4cGVjdChyZXN1bHQuc2hhcGUpLnRvRXF1YWwoWzNdKTtcbiAgICAgICAgZXhwZWN0KHJlc3VsdC5pc0Rpc3Bvc2VkKS50b0JlKGZhbHNlKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBhLCBiIGFyZSBzdGlsbCBoZXJlLCByZXN1bHQgc2hvdWxkIGJlIGRpc3Bvc2VkLlxuICAgICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoMik7XG4gICAgfSk7XG5cbiAgICBleHBlY3QodGYubWVtb3J5KCkubnVtVGVuc29ycykudG9CZSgwKTtcbiAgfSk7XG5cbiAgaXQoJ211bHRpcGxlIGRpc3Bvc2VzIGRvZXMgbm90IGFmZmVjdCBudW0gYXJyYXlzJywgKCkgPT4ge1xuICAgIGV4cGVjdCh0Zi5tZW1vcnkoKS5udW1UZW5zb3JzKS50b0JlKDApO1xuICAgIGNvbnN0IGEgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IGIgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGV4cGVjdCh0Zi5tZW1vcnkoKS5udW1UZW5zb3JzKS50b0JlKDIpO1xuICAgIGEuZGlzcG9zZSgpO1xuICAgIGEuZGlzcG9zZSgpO1xuICAgIGV4cGVjdCh0Zi5tZW1vcnkoKS5udW1UZW5zb3JzKS50b0JlKDEpO1xuICAgIGIuZGlzcG9zZSgpO1xuICAgIGV4cGVjdCh0Zi5tZW1vcnkoKS5udW1UZW5zb3JzKS50b0JlKDApO1xuICB9KTtcblxuICBpdCgnYWxsb3dzIHByaW1pdGl2ZSB0eXBlcycsICgpID0+IHtcbiAgICBjb25zdCBhID0gdGYudGlkeSgoKSA9PiA1KTtcbiAgICBleHBlY3QoYSkudG9CZSg1KTtcblxuICAgIGNvbnN0IGIgPSB0Zi50aWR5KCgpID0+ICdoZWxsbycpO1xuICAgIGV4cGVjdChiKS50b0JlKCdoZWxsbycpO1xuICB9KTtcblxuICBpdCgnYWxsb3dzIGNvbXBsZXggdHlwZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzID0gdGYudGlkeSgoKSA9PiB7XG4gICAgICByZXR1cm4ge2E6IHRmLnNjYWxhcigxKSwgYjogJ2hlbGxvJywgYzogW3RmLnNjYWxhcigyKSwgJ3dvcmxkJ119O1xuICAgIH0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlcy5hLmRhdGEoKSwgWzFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCAocmVzLmNbMF0gYXMgdGYuVGVuc29yKS5kYXRhKCksIFsyXSk7XG4gIH0pO1xuXG4gIGl0KCdyZXR1cm5zIFRlbnNvcltdJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IGIgPSB0Zi50ZW5zb3IxZChbMCwgLTEsIDFdKTtcbiAgICBleHBlY3QodGYubWVtb3J5KCkubnVtVGVuc29ycykudG9CZSgyKTtcblxuICAgIHRmLnRpZHkoKCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGYudGlkeSgoKSA9PiB7XG4gICAgICAgIHRmLmFkZChhLCBiKTtcbiAgICAgICAgcmV0dXJuIFt0Zi5hZGQoYSwgYiksIHRmLnN1YihhLCBiKV07XG4gICAgICB9KTtcblxuICAgICAgLy8gdGhlIDIgcmVzdWx0cyBhcmUgbmV3LiBBbGwgaW50ZXJtZWRpYXRlcyBzaG91bGQgYmUgZGlzcG9zZWQuXG4gICAgICBleHBlY3QodGYubWVtb3J5KCkubnVtVGVuc29ycykudG9CZSg0KTtcbiAgICAgIGV4cGVjdChyZXN1bHRbMF0uaXNEaXNwb3NlZCkudG9CZShmYWxzZSk7XG4gICAgICBleHBlY3QocmVzdWx0WzBdLnNoYXBlKS50b0VxdWFsKFszXSk7XG4gICAgICBleHBlY3QocmVzdWx0WzFdLmlzRGlzcG9zZWQpLnRvQmUoZmFsc2UpO1xuICAgICAgZXhwZWN0KHJlc3VsdFsxXS5zaGFwZSkudG9FcXVhbChbM10pO1xuICAgICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoNCk7XG4gICAgfSk7XG5cbiAgICAvLyB0aGUgMiByZXN1bHRzIHNob3VsZCBiZSBkaXNwb3NlZC5cbiAgICBleHBlY3QodGYubWVtb3J5KCkubnVtVGVuc29ycykudG9CZSgyKTtcbiAgICBhLmRpc3Bvc2UoKTtcbiAgICBiLmRpc3Bvc2UoKTtcbiAgICBleHBlY3QodGYubWVtb3J5KCkubnVtVGVuc29ycykudG9CZSgwKTtcbiAgfSk7XG5cbiAgaXQoJ2Jhc2ljIHVzYWdlIHdpdGhvdXQgcmV0dXJuJywgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGxldCBiID0gdGYudGVuc29yMWQoWzAsIDAsIDBdKTtcblxuICAgIGV4cGVjdCh0Zi5tZW1vcnkoKS5udW1UZW5zb3JzKS50b0JlKDIpO1xuXG4gICAgdGYudGlkeSgoKSA9PiB7XG4gICAgICBiID0gdGYuYWRkKGEsIGIpO1xuICAgICAgYiA9IHRmLmFkZChhLCBiKTtcbiAgICAgIGIgPSB0Zi5hZGQoYSwgYik7XG4gICAgICB0Zi5hZGQoYSwgYik7XG4gICAgfSk7XG5cbiAgICAvLyBhbGwgaW50ZXJtZWRpYXRlcyBzaG91bGQgYmUgZGlzcG9zZWQuXG4gICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoMik7XG4gIH0pO1xuXG4gIGl0KCduZXN0ZWQgdXNhZ2UnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYSA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzXSk7XG4gICAgbGV0IGIgPSB0Zi50ZW5zb3IxZChbMCwgMCwgMF0pO1xuXG4gICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoMik7XG5cbiAgICB0Zi50aWR5KCgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRmLnRpZHkoKCkgPT4ge1xuICAgICAgICBiID0gdGYuYWRkKGEsIGIpO1xuICAgICAgICBiID0gdGYudGlkeSgoKSA9PiB7XG4gICAgICAgICAgYiA9IHRmLnRpZHkoKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRmLmFkZChhLCBiKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvLyBvcmlnaW5hbCBhLCBiLCBhbmQgdHdvIGludGVybWVkaWF0ZXMuXG4gICAgICAgICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoNCk7XG5cbiAgICAgICAgICB0Zi50aWR5KCgpID0+IHtcbiAgICAgICAgICAgIHRmLmFkZChhLCBiKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvLyBBbGwgdGhlIGludGVybWVkaWF0ZXMgc2hvdWxkIGJlIGNsZWFuZWQgdXAuXG4gICAgICAgICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoNCk7XG5cbiAgICAgICAgICByZXR1cm4gdGYuYWRkKGEsIGIpO1xuICAgICAgICB9KTtcbiAgICAgICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoNCk7XG5cbiAgICAgICAgcmV0dXJuIHRmLmFkZChhLCBiKTtcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QodGYubWVtb3J5KCkubnVtVGVuc29ycykudG9CZSgzKTtcbiAgICAgIGV4cGVjdChyZXN1bHQuaXNEaXNwb3NlZCkudG9CZShmYWxzZSk7XG4gICAgICBleHBlY3QocmVzdWx0LnNoYXBlKS50b0VxdWFsKFszXSk7XG4gICAgfSk7XG4gICAgZXhwZWN0KHRmLm1lbW9yeSgpLm51bVRlbnNvcnMpLnRvQmUoMik7XG4gIH0pO1xuXG4gIGl0KCduZXN0ZWQgdXNhZ2UgcmV0dXJucyB0ZW5zb3IgY3JlYXRlZCBmcm9tIG91dHNpZGUgc2NvcGUnLCAoKSA9PiB7XG4gICAgY29uc3QgeCA9IHRmLnNjYWxhcigxKTtcblxuICAgIHRmLnRpZHkoKCkgPT4ge1xuICAgICAgdGYudGlkeSgoKSA9PiB7XG4gICAgICAgIHJldHVybiB4O1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBleHBlY3QoeC5pc0Rpc3Bvc2VkKS50b0JlKGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ25lc3RlZCB1c2FnZSB3aXRoIGtlZXAgd29ya3MnLCAoKSA9PiB7XG4gICAgbGV0IGI6IHRmLlRlbnNvcjtcbiAgICB0Zi50aWR5KCgpID0+IHtcbiAgICAgIGNvbnN0IGEgPSB0Zi5zY2FsYXIoMSk7XG4gICAgICB0Zi50aWR5KCgpID0+IHtcbiAgICAgICAgYiA9IHRmLmtlZXAoYSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGV4cGVjdChiLmlzRGlzcG9zZWQpLnRvQmUoZmFsc2UpO1xuICAgIGIuZGlzcG9zZSgpO1xuICB9KTtcblxuICBpdCgnc2luZ2xlIGFyZ3VtZW50JywgKCkgPT4ge1xuICAgIGxldCBoYXNSYW4gPSBmYWxzZTtcbiAgICB0Zi50aWR5KCgpID0+IHtcbiAgICAgIGhhc1JhbiA9IHRydWU7XG4gICAgfSk7XG4gICAgZXhwZWN0KGhhc1JhbikudG9CZSh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3NpbmdsZSBhcmd1bWVudCwgYnV0IG5vdCBhIGZ1bmN0aW9uIHRocm93cyBlcnJvcicsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgdGYudGlkeSgnYXNkZicpO1xuICAgIH0pLnRvVGhyb3dFcnJvcigpO1xuICB9KTtcblxuICBpdCgnMiBhcmd1bWVudHMsIGZpcnN0IGlzIHN0cmluZycsICgpID0+IHtcbiAgICBsZXQgaGFzUmFuID0gZmFsc2U7XG4gICAgdGYudGlkeSgnbmFtZScsICgpID0+IHtcbiAgICAgIGhhc1JhbiA9IHRydWU7XG4gICAgfSk7XG4gICAgZXhwZWN0KGhhc1JhbikudG9CZSh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJzIgYXJndW1lbnRzLCBidXQgZmlyc3QgaXMgbm90IHN0cmluZyB0aHJvd3MgZXJyb3InLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICAgIHRmLnRpZHkoNCBhcyBhbnksICgpID0+IHt9KTtcbiAgICB9KS50b1Rocm93RXJyb3IoKTtcbiAgfSk7XG5cbiAgaXQoJzIgYXJndW1lbnRzLCBidXQgc2Vjb25kIGlzIG5vdCBhIGZ1bmN0aW9uIHRocm93cyBlcnJvcicsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICAgICAgdGYudGlkeSgnbmFtZScsICdhbm90aGVyIG5hbWUnIGFzIGFueSk7XG4gICAgfSkudG9UaHJvd0Vycm9yKCk7XG4gIH0pO1xuXG4gIGl0KCd3b3JrcyB3aXRoIGFyYml0cmFyeSBkZXB0aCBvZiByZXN1bHQnLCBhc3luYyAoKSA9PiB7XG4gICAgdGYudGlkeSgoKSA9PiB7XG4gICAgICBjb25zdCByZXMgPSB0Zi50aWR5KCgpID0+IHtcbiAgICAgICAgcmV0dXJuIFt0Zi5zY2FsYXIoMSksIFtbdGYuc2NhbGFyKDIpXV0sIHtsaXN0OiBbdGYuc2NhbGFyKDMpXX1dO1xuICAgICAgfSk7XG4gICAgICBleHBlY3QoKHJlc1swXSBhcyB0Zi5UZW5zb3IpLmlzRGlzcG9zZWQpLnRvQmUoZmFsc2UpO1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICAgICAgZXhwZWN0KChyZXNbMV0gYXMgYW55KVswXVswXS5pc0Rpc3Bvc2VkKS50b0JlKGZhbHNlKTtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICAgIGV4cGVjdCgocmVzWzJdIGFzIGFueSkubGlzdFswXS5pc0Rpc3Bvc2VkKS50b0JlKGZhbHNlKTtcbiAgICAgIGV4cGVjdCh0Zi5tZW1vcnkoKS5udW1UZW5zb3JzKS50b0JlKDMpO1xuICAgICAgcmV0dXJuIHJlc1swXTtcbiAgICB9KTtcbiAgICAvLyBFdmVyeXRoaW5nIGJ1dCBzY2FsYXIoMSkgZ290IGRpc3Bvc2VkLlxuICAgIGV4cGVjdCh0Zi5tZW1vcnkoKS5udW1UZW5zb3JzKS50b0JlKDEpO1xuICB9KTtcbn0pO1xuIl19
\No newline at end of file