Ly8NCi8vIKkgQ29weXJpZ2h0IEhlbnJpayBSYXZuIDIwMDQNCi8vDQovLyBVc2UsIG1vZGlmaWNhdGlvbiBhbmQgZGlzdHJpYnV0aW9uIGFyZSBzdWJqZWN0IHRvIHRoZSBCb29zdCBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEuMC4NCi8vIChTZWUgYWNjb21wYW55aW5nIGZpbGUgTElDRU5TRV8xXzAudHh0IG9yIGNvcHkgYXQgaHR0cDovL3d3dy5ib29zdC5vcmcvTElDRU5TRV8xXzAudHh0KQ0KLy8NCg0KdXNpbmcgU3lzdGVtOw0KdXNpbmcgU3lzdGVtLkNvbGxlY3Rpb25zOw0KdXNpbmcgU3lzdGVtLklPOw0KDQovLyB1bmNvbW1lbnQgdGhlIGRlZmluZSBiZWxvdyB0byBpbmNsdWRlIHVuaXQgdGVzdHMNCi8vI2RlZmluZSBudW5pdA0KI2lmIG51bml0DQp1c2luZyBOVW5pdC5GcmFtZXdvcms7DQoNCi8vIFVuaXQgdGVzdHMgZm9yIHRoZSBEb3RaTGliIGNsYXNzIGxpYnJhcnkNCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCi8vDQovLyBVc2UgdGhpcyB3aXRoIE5Vbml0IDIgZnJvbSBodHRwOi8vd3d3Lm51bml0Lm9yZw0KLy8NCg0KbmFtZXNwYWNlIERvdFpMaWJUZXN0cw0Kew0KICAgIHVzaW5nIERvdFpMaWI7DQoNCiAgICAvLyBoZWxwZXIgbWV0aG9kcw0KICAgIGludGVybmFsIGNsYXNzIFV0aWxzDQogICAgew0KICAgICAgICBwdWJsaWMgc3RhdGljIGJvb2wgYnl0ZUFyckVxdWFsKCBieXRlW10gbGhzLCBieXRlW10gcmhzICkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKGxocy5MZW5ndGggIT0gcmhzLkxlbmd0aCkNCiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7DQogICAgICAgICAgICBmb3IgKGludCBpID0gbGhzLkxlbmd0aC0xOyBpID49IDA7IC0taSkNCiAgICAgICAgICAgICAgICBpZiAobGhzW2ldICE9IHJoc1tpXSkNCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOw0KICAgICAgICAgICAgcmV0dXJuIHRydWU7DQogICAgICAgIH0NCg0KICAgIH0NCg0KDQogICAgW1Rlc3RGaXh0dXJlXQ0KICAgIHB1YmxpYyBjbGFzcyBDaXJjQnVmZmVyVGVzdHMNCiAgICB7DQogICAgICAgICNyZWdpb24gQ2lyY3VsYXIgYnVmZmVyIHRlc3RzDQogICAgICAgIFtUZXN0XQ0KICAgICAgICBwdWJsaWMgdm9pZCBTaW5nbGVQdXRHZXQoKQ0KICAgICAgICB7DQogICAgICAgICAgICBDaXJjdWxhckJ1ZmZlciBidWYgPSBuZXcgQ2lyY3VsYXJCdWZmZXIoMTApOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCAwLCBidWYuU2l6ZSApOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCAtMSwgYnVmLkdldCgpICk7DQoNCiAgICAgICAgICAgIEFzc2VydC5Jc1RydWUoYnVmLlB1dCggMSApKTsNCiAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCggMSwgYnVmLlNpemUgKTsNCiAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCggMSwgYnVmLkdldCgpICk7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoIDAsIGJ1Zi5TaXplICk7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoIC0xLCBidWYuR2V0KCkgKTsNCiAgICAgICAgfQ0KDQogICAgICAgIFtUZXN0XQ0KICAgICAgICBwdWJsaWMgdm9pZCBCbG9ja1B1dEdldCgpDQogICAgICAgIHsNCiAgICAgICAgICAgIENpcmN1bGFyQnVmZmVyIGJ1ZiA9IG5ldyBDaXJjdWxhckJ1ZmZlcigxMCk7DQogICAgICAgICAgICBieXRlW10gYXJyID0gezEsMiwzLDQsNSw2LDcsOCw5LDEwfTsNCiAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCggMTAsIGJ1Zi5QdXQoYXJyLDAsMTApICk7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoIDEwLCBidWYuU2l6ZSApOw0KICAgICAgICAgICAgQXNzZXJ0LklzRmFsc2UoIGJ1Zi5QdXQoMTEpICk7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoIDEsIGJ1Zi5HZXQoKSApOw0KICAgICAgICAgICAgQXNzZXJ0LklzVHJ1ZSggYnVmLlB1dCgxMSkgKTsNCg0KICAgICAgICAgICAgYnl0ZVtdIGFycjIgPSAoYnl0ZVtdKWFyci5DbG9uZSgpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCA5LCBidWYuR2V0KGFycjIsMSw5KSApOw0KICAgICAgICAgICAgQXNzZXJ0LklzVHJ1ZSggVXRpbHMuYnl0ZUFyckVxdWFsKGFycixhcnIyKSApOw0KICAgICAgICB9DQoNCiAgICAgICAgI2VuZHJlZ2lvbg0KICAgIH0NCg0KICAgIFtUZXN0Rml4dHVyZV0NCiAgICBwdWJsaWMgY2xhc3MgQ2hlY2tzdW1UZXN0cw0KICAgIHsNCiAgICAgICAgI3JlZ2lvbiBDUkMzMiBUZXN0cw0KICAgICAgICBbVGVzdF0NCiAgICAgICAgcHVibGljIHZvaWQgQ1JDMzJfTnVsbCgpDQogICAgICAgIHsNCiAgICAgICAgICAgIENSQzMyQ2hlY2tzdW0gY3JjMzIgPSBuZXcgQ1JDMzJDaGVja3N1bSgpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCAwLCBjcmMzMi5WYWx1ZSApOw0KDQogICAgICAgICAgICBjcmMzMiA9IG5ldyBDUkMzMkNoZWNrc3VtKDEpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCAxLCBjcmMzMi5WYWx1ZSApOw0KDQogICAgICAgICAgICBjcmMzMiA9IG5ldyBDUkMzMkNoZWNrc3VtKDU1Nik7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoIDU1NiwgY3JjMzIuVmFsdWUgKTsNCiAgICAgICAgfQ0KDQogICAgICAgIFtUZXN0XQ0KICAgICAgICBwdWJsaWMgdm9pZCBDUkMzMl9EYXRhKCkNCiAgICAgICAgew0KICAgICAgICAgICAgQ1JDMzJDaGVja3N1bSBjcmMzMiA9IG5ldyBDUkMzMkNoZWNrc3VtKCk7DQogICAgICAgICAgICBieXRlW10gZGF0YSA9IHsgMSwyLDMsNCw1LDYsNyB9Ow0KICAgICAgICAgICAgY3JjMzIuVXBkYXRlKGRhdGEpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCAweDcwZTQ2ODg4LCBjcmMzMi5WYWx1ZSAgKTsNCg0KICAgICAgICAgICAgY3JjMzIgPSBuZXcgQ1JDMzJDaGVja3N1bSgpOw0KICAgICAgICAgICAgY3JjMzIuVXBkYXRlKCJwZW5ndWluIik7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoIDB4MGU1YzFhMTIwLCBjcmMzMi5WYWx1ZSApOw0KDQogICAgICAgICAgICBjcmMzMiA9IG5ldyBDUkMzMkNoZWNrc3VtKDEpOw0KICAgICAgICAgICAgY3JjMzIuVXBkYXRlKCJwZW5ndWluIik7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoMHg0M2I2YWE5NCwgY3JjMzIuVmFsdWUpOw0KDQogICAgICAgIH0NCiAgICAgICAgI2VuZHJlZ2lvbg0KDQogICAgICAgICNyZWdpb24gQWRsZXIgdGVzdHMNCg0KICAgICAgICBbVGVzdF0NCiAgICAgICAgcHVibGljIHZvaWQgQWRsZXJfTnVsbCgpDQogICAgICAgIHsNCiAgICAgICAgICAgIEFkbGVyQ2hlY2tzdW0gYWRsZXIgPSBuZXcgQWRsZXJDaGVja3N1bSgpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKDAsIGFkbGVyLlZhbHVlKTsNCg0KICAgICAgICAgICAgYWRsZXIgPSBuZXcgQWRsZXJDaGVja3N1bSgxKTsNCiAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCggMSwgYWRsZXIuVmFsdWUgKTsNCg0KICAgICAgICAgICAgYWRsZXIgPSBuZXcgQWRsZXJDaGVja3N1bSg1NTYpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCA1NTYsIGFkbGVyLlZhbHVlICk7DQogICAgICAgIH0NCg0KICAgICAgICBbVGVzdF0NCiAgICAgICAgcHVibGljIHZvaWQgQWRsZXJfRGF0YSgpDQogICAgICAgIHsNCiAgICAgICAgICAgIEFkbGVyQ2hlY2tzdW0gYWRsZXIgPSBuZXcgQWRsZXJDaGVja3N1bSgxKTsNCiAgICAgICAgICAgIGJ5dGVbXSBkYXRhID0geyAxLDIsMyw0LDUsNiw3IH07DQogICAgICAgICAgICBhZGxlci5VcGRhdGUoZGF0YSk7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoIDB4NWIwMDFkLCBhZGxlci5WYWx1ZSAgKTsNCg0KICAgICAgICAgICAgYWRsZXIgPSBuZXcgQWRsZXJDaGVja3N1bSgpOw0KICAgICAgICAgICAgYWRsZXIuVXBkYXRlKCJwZW5ndWluIik7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoMHgwYmNmMDJmNiwgYWRsZXIuVmFsdWUgKTsNCg0KICAgICAgICAgICAgYWRsZXIgPSBuZXcgQWRsZXJDaGVja3N1bSgxKTsNCiAgICAgICAgICAgIGFkbGVyLlVwZGF0ZSgicGVuZ3VpbiIpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKDB4MGJkNjAyZjcsIGFkbGVyLlZhbHVlKTsNCg0KICAgICAgICB9DQogICAgICAgICNlbmRyZWdpb24NCiAgICB9DQoNCiAgICBbVGVzdEZpeHR1cmVdDQogICAgcHVibGljIGNsYXNzIEluZm9UZXN0cw0KICAgIHsNCiAgICAgICAgI3JlZ2lvbiBJbmZvIHRlc3RzDQogICAgICAgIFtUZXN0XQ0KICAgICAgICBwdWJsaWMgdm9pZCBJbmZvX1ZlcnNpb24oKQ0KICAgICAgICB7DQogICAgICAgICAgICBJbmZvIGluZm8gPSBuZXcgSW5mbygpOw0KICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKCIxLjIuNC41IiwgSW5mby5WZXJzaW9uKTsNCiAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCgzMiwgaW5mby5TaXplT2ZVSW50KTsNCiAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCgzMiwgaW5mby5TaXplT2ZVTG9uZyk7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoMzIsIGluZm8uU2l6ZU9mUG9pbnRlcik7DQogICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoMzIsIGluZm8uU2l6ZU9mT2Zmc2V0KTsNCiAgICAgICAgfQ0KICAgICAgICAjZW5kcmVnaW9uDQogICAgfQ0KDQogICAgW1Rlc3RGaXh0dXJlXQ0KICAgIHB1YmxpYyBjbGFzcyBEZWZsYXRlSW5mbGF0ZVRlc3RzDQogICAgew0KICAgICAgICAjcmVnaW9uIERlZmxhdGUgdGVzdHMNCiAgICAgICAgW1Rlc3RdDQogICAgICAgIHB1YmxpYyB2b2lkIERlZmxhdGVfSW5pdCgpDQogICAgICAgIHsNCiAgICAgICAgICAgIHVzaW5nIChEZWZsYXRlciBkZWYgPSBuZXcgRGVmbGF0ZXIoQ29tcHJlc3NMZXZlbC5EZWZhdWx0KSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIHByaXZhdGUgQXJyYXlMaXN0IGNvbXByZXNzZWREYXRhID0gbmV3IEFycmF5TGlzdCgpOw0KICAgICAgICBwcml2YXRlIHVpbnQgYWRsZXIxOw0KDQogICAgICAgIHByaXZhdGUgQXJyYXlMaXN0IHVuY29tcHJlc3NlZERhdGEgPSBuZXcgQXJyYXlMaXN0KCk7DQogICAgICAgIHByaXZhdGUgdWludCBhZGxlcjI7DQoNCiAgICAgICAgcHVibGljIHZvaWQgQ0RhdGFBdmFpbChieXRlW10gZGF0YSwgaW50IHN0YXJ0SW5kZXgsIGludCBjb3VudCkNCiAgICAgICAgew0KICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBjb3VudDsgKytpKQ0KICAgICAgICAgICAgICAgIGNvbXByZXNzZWREYXRhLkFkZChkYXRhW2krc3RhcnRJbmRleF0pOw0KICAgICAgICB9DQoNCiAgICAgICAgW1Rlc3RdDQogICAgICAgIHB1YmxpYyB2b2lkIERlZmxhdGVfQ29tcHJlc3MoKQ0KICAgICAgICB7DQogICAgICAgICAgICBjb21wcmVzc2VkRGF0YS5DbGVhcigpOw0KDQogICAgICAgICAgICBieXRlW10gdGVzdERhdGEgPSBuZXcgYnl0ZVszNTAwMF07DQogICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHRlc3REYXRhLkxlbmd0aDsgKytpKQ0KICAgICAgICAgICAgICAgIHRlc3REYXRhW2ldID0gNTsNCg0KICAgICAgICAgICAgdXNpbmcgKERlZmxhdGVyIGRlZiA9IG5ldyBEZWZsYXRlcigoQ29tcHJlc3NMZXZlbCk1KSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBkZWYuRGF0YUF2YWlsYWJsZSArPSBuZXcgRGF0YUF2YWlsYWJsZUhhbmRsZXIoQ0RhdGFBdmFpbCk7DQogICAgICAgICAgICAgICAgZGVmLkFkZCh0ZXN0RGF0YSk7DQogICAgICAgICAgICAgICAgZGVmLkZpbmlzaCgpOw0KICAgICAgICAgICAgICAgIGFkbGVyMSA9IGRlZi5DaGVja3N1bTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICAjZW5kcmVnaW9uDQoNCiAgICAgICAgI3JlZ2lvbiBJbmZsYXRlIHRlc3RzDQogICAgICAgIFtUZXN0XQ0KICAgICAgICBwdWJsaWMgdm9pZCBJbmZsYXRlX0luaXQoKQ0KICAgICAgICB7DQogICAgICAgICAgICB1c2luZyAoSW5mbGF0ZXIgaW5mID0gbmV3IEluZmxhdGVyKCkpDQogICAgICAgICAgICB7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBwcml2YXRlIHZvaWQgRERhdGFBdmFpbChieXRlW10gZGF0YSwgaW50IHN0YXJ0SW5kZXgsIGludCBjb3VudCkNCiAgICAgICAgew0KICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBjb3VudDsgKytpKQ0KICAgICAgICAgICAgICAgIHVuY29tcHJlc3NlZERhdGEuQWRkKGRhdGFbaStzdGFydEluZGV4XSk7DQogICAgICAgIH0NCg0KICAgICAgICBbVGVzdF0NCiAgICAgICAgcHVibGljIHZvaWQgSW5mbGF0ZV9FeHBhbmQoKQ0KICAgICAgICB7DQogICAgICAgICAgICB1bmNvbXByZXNzZWREYXRhLkNsZWFyKCk7DQoNCiAgICAgICAgICAgIHVzaW5nIChJbmZsYXRlciBpbmYgPSBuZXcgSW5mbGF0ZXIoKSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBpbmYuRGF0YUF2YWlsYWJsZSArPSBuZXcgRGF0YUF2YWlsYWJsZUhhbmRsZXIoRERhdGFBdmFpbCk7DQogICAgICAgICAgICAgICAgaW5mLkFkZCgoYnl0ZVtdKWNvbXByZXNzZWREYXRhLlRvQXJyYXkodHlwZW9mKGJ5dGUpKSk7DQogICAgICAgICAgICAgICAgaW5mLkZpbmlzaCgpOw0KICAgICAgICAgICAgICAgIGFkbGVyMiA9IGluZi5DaGVja3N1bTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCggYWRsZXIxLCBhZGxlcjIgKTsNCiAgICAgICAgfQ0KICAgICAgICAjZW5kcmVnaW9uDQogICAgfQ0KDQogICAgW1Rlc3RGaXh0dXJlXQ0KICAgIHB1YmxpYyBjbGFzcyBHWmlwU3RyZWFtVGVzdHMNCiAgICB7DQogICAgICAgICNyZWdpb24gR1ppcFN0cmVhbSB0ZXN0DQogICAgICAgIFtUZXN0XQ0KICAgICAgICBwdWJsaWMgdm9pZCBHWmlwU3RyZWFtX1dyaXRlUmVhZCgpDQogICAgICAgIHsNCiAgICAgICAgICAgIHVzaW5nIChHWmlwU3RyZWFtIGd6T3V0ID0gbmV3IEdaaXBTdHJlYW0oImd6c3RyZWFtLmd6IiwgQ29tcHJlc3NMZXZlbC5CZXN0KSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBCaW5hcnlXcml0ZXIgd3JpdGVyID0gbmV3IEJpbmFyeVdyaXRlcihnek91dCk7DQogICAgICAgICAgICAgICAgd3JpdGVyLldyaXRlKCJoaSB0aGVyZSIpOw0KICAgICAgICAgICAgICAgIHdyaXRlci5Xcml0ZShNYXRoLlBJKTsNCiAgICAgICAgICAgICAgICB3cml0ZXIuV3JpdGUoNDIpOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICB1c2luZyAoR1ppcFN0cmVhbSBnekluID0gbmV3IEdaaXBTdHJlYW0oImd6c3RyZWFtLmd6IikpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgQmluYXJ5UmVhZGVyIHJlYWRlciA9IG5ldyBCaW5hcnlSZWFkZXIoZ3pJbik7DQogICAgICAgICAgICAgICAgc3RyaW5nIHMgPSByZWFkZXIuUmVhZFN0cmluZygpOw0KICAgICAgICAgICAgICAgIEFzc2VydC5BcmVFcXVhbCgiaGkgdGhlcmUiLHMpOw0KICAgICAgICAgICAgICAgIGRvdWJsZSBkID0gcmVhZGVyLlJlYWREb3VibGUoKTsNCiAgICAgICAgICAgICAgICBBc3NlcnQuQXJlRXF1YWwoTWF0aC5QSSwgZCk7DQogICAgICAgICAgICAgICAgaW50IGkgPSByZWFkZXIuUmVhZEludDMyKCk7DQogICAgICAgICAgICAgICAgQXNzZXJ0LkFyZUVxdWFsKDQyLGkpOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgIH0NCiAgICAgICAgI2VuZHJlZ2lvbg0KCX0NCn0NCg0KI2VuZGlmDQo=