PCEtLQogIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmUKICBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gU2VlIHRoZSBOT1RJQ0UgZmlsZQogIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uCiAgcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlCiAgdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZQogICJMaWNlbnNlIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2UKICB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKCiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKCiAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLAogIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuCiAgIkFTIElTIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZCiAgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUKICBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zCiAgdW5kZXIgdGhlIExpY2Vuc2UuCi0tPgoKPGh0bWw+CjxoZWFkPgogIDx0aXRsZT5UaHJpZnQgSmF2YXNjcmlwdCBCaW5kaW5ncyAtIEV4YW1wbGU8L3RpdGxlPgoKICA8c2NyaXB0IHNyYz0iL3RocmlmdC5qcyIgICAgICAgICAgICAgICAgIHR5cGU9InRleHQvamF2YXNjcmlwdCI+PC9zY3JpcHQ+CiAgPHNjcmlwdCBzcmM9Imdlbi1qcy9UaHJpZnRUZXN0X3R5cGVzLmpzIiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPjwvc2NyaXB0PgogIDxzY3JpcHQgc3JjPSJnZW4tanMvVGhyaWZ0VGVzdC5qcyIgICAgICAgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij48L3NjcmlwdD4KCiAgPCEtLSBmb3IgYXN5bmMgZXhhbXBsZSAtLT4KICA8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJodHRwOi8vYWpheC5nb29nbGVhcGlzLmNvbS9hamF4L2xpYnMvanF1ZXJ5LzEuMy4yL2pxdWVyeS5taW4uanMiPjwvc2NyaXB0PgoKPC9oZWFkPgo8Ym9keSBpZD0iYm9keSI+Cgo8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0Ij4KCiAgLy9jcmVhdGUgY2xpZW50CiAgdmFyIHRyYW5zcG9ydCA9IG5ldyBUaHJpZnQuVHJhbnNwb3J0KCIvc2VydmljZSIpCiAgdmFyIHByb3RvY29sICA9IG5ldyBUaHJpZnQuUHJvdG9jb2wodHJhbnNwb3J0KQogIHZhciBjbGllbnQgICAgPSBuZXcgVGhyaWZ0VGVzdC5UaHJpZnRUZXN0Q2xpZW50KHByb3RvY29sKQoKICAvL2NyZWF0ZSBpbnNhbml0eSBvYmoKICB2YXIgaW5zYW5pdHkgID0gbmV3IFRocmlmdFRlc3QuSW5zYW5pdHkoKQogIGluc2FuaXR5LnVzZXJNYXBbVGhyaWZ0VGVzdC5OdW1iZXJ6Lk9ORV0gPSAxCiAgaW5zYW5pdHkudXNlck1hcFtUaHJpZnRUZXN0Lk51bWJlcnouVFdPXSA9IDIKCiAgdmFyIHh0ciA9IG5ldyBUaHJpZnRUZXN0Llh0cnVjdCgpCiAgeHRyLnN0cmluZ190aGluZyA9ICd3b3JrZWQnCiAgaW5zYW5pdHkueHRydWN0cy5wdXNoKHh0cikKCiAgdmFyIHh0cjI9IG5ldyBUaHJpZnRUZXN0Llh0cnVjdDIoKQogIHh0cjIuc3RydWN0X3RoaW5nID0geHRyCgogIHZhciBsaXN0ID0gWzEsMiwzXQoKICAvL3J1biB0ZXN0cyBzeW5jaHJvbm91c2x5CgogIGRvY3VtZW50LndyaXRlKCI8aDI+PHU+VGhyaWZ0IEphdmFzY3JpcHQgQmluZGluZ3M8L3U+PC9oMj4iKQogIGRvY3VtZW50LndyaXRlKCI8aDI+U3luY2hyb25vdXMgRXhhbXBsZTwvaDI+IikKICBkb2N1bWVudC53cml0ZSgiY2xpZW50LnRlc3RTdHJpbmcoKSA9PiAiKyhjbGllbnQudGVzdFN0cmluZygid29ya3MiKSAgICAgPT0gIndvcmtzIikrIjxici8+IikKICBkb2N1bWVudC53cml0ZSgiY2xpZW50LnRlc3RTdHJpbmcodXRmLTgpID0+ICIrKGNsaWVudC50ZXN0U3RyaW5nKCJhh46Sl5xlIikgICA9PSAiYYeOkpecZSIpKyI8YnIvPiIpCiAgZG9jdW1lbnQud3JpdGUoImNsaWVudC50ZXN0RG91YmxlKCkgPT4gIisoY2xpZW50LnRlc3REb3VibGUoMy4xNCkgICAgICAgID09IDMuMTQpKyI8YnIvPiIpCiAgZG9jdW1lbnQud3JpdGUoImNsaWVudC50ZXN0Qnl0ZSgpICAgPT4gIisoY2xpZW50LnRlc3RCeXRlKDB4MDEpICAgICAgICAgID09IDB4MDEpKyI8YnIvPiIpCiAgZG9jdW1lbnQud3JpdGUoImNsaWVudC50ZXN0STMyKCkgICAgPT4gIisoY2xpZW50LnRlc3RJMzIoTWF0aC5wb3coMiwzMCkpID09IE1hdGgucG93KDIsMzApKSsiPGJyLz4iKQogIGRvY3VtZW50LndyaXRlKCJjbGllbnQudGVzdEk2NCgpICAgID0+ICIrKGNsaWVudC50ZXN0STY0KE1hdGgucG93KDIsNjApKSA9PSBNYXRoLnBvdygyLDYwKSkrIjxici8+IikKICBkb2N1bWVudC53cml0ZSgiY2xpZW50LnRlc3RTdHJ1Y3QoKSA9PiAiKyhjbGllbnQudGVzdFN0cnVjdCh4dHIpLnN0cmluZ190aGluZyA9PSAid29ya2VkIikrIjxici8+IikKICBkb2N1bWVudC53cml0ZSgiY2xpZW50LnRlc3ROZXN0KCkgICA9PiAiKyhjbGllbnQudGVzdE5lc3QoeHRyMikuc3RydWN0X3RoaW5nLnN0cmluZ190aGluZyA9PSAid29ya2VkIikrIjxici8+IikKICBkb2N1bWVudC53cml0ZSgiY2xpZW50LnRlc3RNYXAoKSAgICA9PiAiKyhjbGllbnQudGVzdE1hcChpbnNhbml0eS51c2VyTWFwKVtUaHJpZnRUZXN0Lk51bWJlcnouT05FXSA9PSAxKSsiPGJyLz4iKQogIGRvY3VtZW50LndyaXRlKCJjbGllbnQudGVzdExpc3QoKSAgID0+ICIrKGNsaWVudC50ZXN0TGlzdChsaXN0KS5sZW5ndGggPT0gMykrIjxici8+IikKICBkb2N1bWVudC53cml0ZSgiY2xpZW50LnRlc3RTZXQoKSAgICA9PiAiKyhjbGllbnQudGVzdFNldChsaXN0KS5sZW5ndGggPT0gMykrIjxici8+IikKICBkb2N1bWVudC53cml0ZSgiY2xpZW50LnRlc3RFbnVtKCkgICA9PiAiKyhjbGllbnQudGVzdEVudW0oVGhyaWZ0VGVzdC5OdW1iZXJ6Lk9ORSkgPT0gVGhyaWZ0VGVzdC5OdW1iZXJ6Lk9ORSkrIjxici8+IikKCiAgZG9jdW1lbnQud3JpdGUoImNsaWVudC50ZXN0RXhjZXB0aW9uKCkgPT4gIikKICB0cnl7CiAgICBjbGllbnQudGVzdEV4Y2VwdGlvbigiZ28iKQogICAgZG9jdW1lbnQud3JpdGUoImZhbHNlPGJyLz4iKQogIH1jYXRjaChlKXsKICAgIGRvY3VtZW50LndyaXRlKCJ0cnVlPGJyLz4iKQogIH0KCiAgZG9jdW1lbnQud3JpdGUoImNsaWVudC50ZXN0SW5zYW5pdHkoKSA9PiAiKQogIHZhciByZXMgPSBjbGllbnQudGVzdEluc2FuaXR5KGluc2FuaXR5KQoKICBkb2N1bWVudC53cml0ZSgocmVzWyIxIl1bIjEiXS54dHJ1Y3RzWzBdLnN0cmluZ190aGluZyA9PSAid29ya2VkIikrIjxici8+IikKCiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogIC8vUnVuIHNhbWUgdGVzdHMgYXN5bmNocm9ub3VzbHkKCiAgdmFyIHRyYW5zcG9ydCA9IG5ldyBUaHJpZnQuVHJhbnNwb3J0KCkKICB2YXIgcHJvdG9jb2wgID0gbmV3IFRocmlmdC5Qcm90b2NvbCh0cmFuc3BvcnQpCiAgdmFyIGNsaWVudCAgICA9IG5ldyBUaHJpZnRUZXN0LlRocmlmdFRlc3RDbGllbnQocHJvdG9jb2wpCgogIGRvY3VtZW50LndyaXRlKCI8aDI+QXN5bmNocm9ub3VzIEV4YW1wbGU8L2gyPiIpCiAgalF1ZXJ5LmFqYXgoewogICAgIHVybDogIi9zZXJ2aWNlIiwKICAgICBkYXRhOiBjbGllbnQuc2VuZF90ZXN0STMyKE1hdGgucG93KDIsMzApKSwKICAgICB0eXBlOiAiUE9TVCIsCiAgICAgY2FjaGU6IGZhbHNlLAogICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlcyl7CiAgICAgICAgICAgIHZhciBfdHJhbnNwb3J0ID0gbmV3IFRocmlmdC5UcmFuc3BvcnQoKQogICAgICAgICAgICB2YXIgX3Byb3RvY29sICA9IG5ldyBUaHJpZnQuUHJvdG9jb2woX3RyYW5zcG9ydCkKICAgICAgICAgICAgdmFyIF9jbGllbnQgICAgPSBuZXcgVGhyaWZ0VGVzdC5UaHJpZnRUZXN0Q2xpZW50KF9wcm90b2NvbCkKCiAgICAgICAgICAgIF90cmFuc3BvcnQuc2V0UmVjdkJ1ZmZlciggcmVzICkKCiAgICAgICAgICAgIHZhciB2ID0gIF9jbGllbnQucmVjdl90ZXN0STMyKCkKICAgICAgICAgICAgJCgiI2JvZHkiKS5hcHBlbmQoImNsaWVudC50ZXN0STMyKCkgICAgPT4gIisodiA9PSBNYXRoLnBvdygyLDMwKSkrIjxici8+IikKCiAgICAgfQogIH0pCgogIGpRdWVyeS5hamF4KHsKICAgICB1cmw6ICIvc2VydmljZSIsCiAgICAgZGF0YTogY2xpZW50LnNlbmRfdGVzdEk2NChNYXRoLnBvdygyLDYwKSksCiAgICAgdHlwZTogIlBPU1QiLAogICAgIGNhY2hlOiBmYWxzZSwKICAgICBzdWNjZXNzOiBmdW5jdGlvbihyZXMpewogICAgICAgICAgICB2YXIgX3RyYW5zcG9ydCA9IG5ldyBUaHJpZnQuVHJhbnNwb3J0KCkKICAgICAgICAgICAgdmFyIF9wcm90b2NvbCAgPSBuZXcgVGhyaWZ0LlByb3RvY29sKF90cmFuc3BvcnQpCiAgICAgICAgICAgIHZhciBfY2xpZW50ICAgID0gbmV3IFRocmlmdFRlc3QuVGhyaWZ0VGVzdENsaWVudChfcHJvdG9jb2wpCgogICAgICAgICAgICBfdHJhbnNwb3J0LnNldFJlY3ZCdWZmZXIoIHJlcyApCgogICAgICAgICAgICB2YXIgdiA9ICBfY2xpZW50LnJlY3ZfdGVzdEk2NCgpCiAgICAgICAgICAgICQoIiNib2R5IikuYXBwZW5kKCJjbGllbnQudGVzdEk2NCgpICAgID0+ICIrKHYgPT0gTWF0aC5wb3coMiw2MCkpKyI8YnIvPiIpCgogICAgIH0KICB9KQoKCgo8L3NjcmlwdD4KCjwvYm9keT4KPC9odG1sPgo=