Iy0qLSBjb2Rpbmc6IElTTy04ODU5LTEgLSotCiMgcHlzcWxpdGUyL3Rlc3QvZmFjdG9yeS5weTogdGVzdHMgZm9yIHRoZSB2YXJpb3VzIGZhY3RvcmllcyBpbiBweXNxbGl0ZQojCiMgQ29weXJpZ2h0IChDKSAyMDA1LTIwMDcgR2VyaGFyZCBI5HJpbmcgPGdoQGdoYWVyaW5nLmRlPgojCiMgVGhpcyBmaWxlIGlzIHBhcnQgb2YgcHlzcWxpdGUuCiMKIyBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkICdhcy1pcycsIHdpdGhvdXQgYW55IGV4cHJlc3Mgb3IgaW1wbGllZAojIHdhcnJhbnR5LiAgSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXMKIyBhcmlzaW5nIGZyb20gdGhlIHVzZSBvZiB0aGlzIHNvZnR3YXJlLgojCiMgUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsCiMgaW5jbHVkaW5nIGNvbW1lcmNpYWwgYXBwbGljYXRpb25zLCBhbmQgdG8gYWx0ZXIgaXQgYW5kIHJlZGlzdHJpYnV0ZSBpdAojIGZyZWVseSwgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIHJlc3RyaWN0aW9uczoKIwojIDEuIFRoZSBvcmlnaW4gb2YgdGhpcyBzb2Z0d2FyZSBtdXN0IG5vdCBiZSBtaXNyZXByZXNlbnRlZDsgeW91IG11c3Qgbm90CiMgICAgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmUKIyAgICBpbiBhIHByb2R1Y3QsIGFuIGFja25vd2xlZGdtZW50IGluIHRoZSBwcm9kdWN0IGRvY3VtZW50YXRpb24gd291bGQgYmUKIyAgICBhcHByZWNpYXRlZCBidXQgaXMgbm90IHJlcXVpcmVkLgojIDIuIEFsdGVyZWQgc291cmNlIHZlcnNpb25zIG11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaCwgYW5kIG11c3Qgbm90IGJlCiMgICAgbWlzcmVwcmVzZW50ZWQgYXMgYmVpbmcgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLgojIDMuIFRoaXMgbm90aWNlIG1heSBub3QgYmUgcmVtb3ZlZCBvciBhbHRlcmVkIGZyb20gYW55IHNvdXJjZSBkaXN0cmlidXRpb24uCgppbXBvcnQgdW5pdHRlc3QKaW1wb3J0IHNxbGl0ZTMgYXMgc3FsaXRlCgpjbGFzcyBNeUNvbm5lY3Rpb24oc3FsaXRlLkNvbm5lY3Rpb24pOgogICAgZGVmIF9faW5pdF9fKHNlbGYsICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgc3FsaXRlLkNvbm5lY3Rpb24uX19pbml0X18oc2VsZiwgKmFyZ3MsICoqa3dhcmdzKQoKZGVmIGRpY3RfZmFjdG9yeShjdXJzb3IsIHJvdyk6CiAgICBkID0ge30KICAgIGZvciBpZHgsIGNvbCBpbiBlbnVtZXJhdGUoY3Vyc29yLmRlc2NyaXB0aW9uKToKICAgICAgICBkW2NvbFswXV0gPSByb3dbaWR4XQogICAgcmV0dXJuIGQKCmNsYXNzIE15Q3Vyc29yKHNxbGl0ZS5DdXJzb3IpOgogICAgZGVmIF9faW5pdF9fKHNlbGYsICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgc3FsaXRlLkN1cnNvci5fX2luaXRfXyhzZWxmLCAqYXJncywgKiprd2FyZ3MpCiAgICAgICAgc2VsZi5yb3dfZmFjdG9yeSA9IGRpY3RfZmFjdG9yeQoKY2xhc3MgQ29ubmVjdGlvbkZhY3RvcnlUZXN0cyh1bml0dGVzdC5UZXN0Q2FzZSk6CiAgICBkZWYgc2V0VXAoc2VsZik6CiAgICAgICAgc2VsZi5jb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiLCBmYWN0b3J5PU15Q29ubmVjdGlvbikKCiAgICBkZWYgdGVhckRvd24oc2VsZik6CiAgICAgICAgc2VsZi5jb24uY2xvc2UoKQoKICAgIGRlZiBDaGVja0lzSW5zdGFuY2Uoc2VsZik6CiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKGlzaW5zdGFuY2Uoc2VsZi5jb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTXlDb25uZWN0aW9uKSwKICAgICAgICAgICAgICAgICAgICAgICAgImNvbm5lY3Rpb24gaXMgbm90IGluc3RhbmNlIG9mIE15Q29ubmVjdGlvbiIpCgpjbGFzcyBDdXJzb3JGYWN0b3J5VGVzdHModW5pdHRlc3QuVGVzdENhc2UpOgogICAgZGVmIHNldFVwKHNlbGYpOgogICAgICAgIHNlbGYuY29uID0gc3FsaXRlLmNvbm5lY3QoIjptZW1vcnk6IikKCiAgICBkZWYgdGVhckRvd24oc2VsZik6CiAgICAgICAgc2VsZi5jb24uY2xvc2UoKQoKICAgIGRlZiBDaGVja0lzSW5zdGFuY2Uoc2VsZik6CiAgICAgICAgY3VyID0gc2VsZi5jb24uY3Vyc29yKGZhY3Rvcnk9TXlDdXJzb3IpCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKGlzaW5zdGFuY2UoY3VyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE15Q3Vyc29yKSwKICAgICAgICAgICAgICAgICAgICAgICAgImN1cnNvciBpcyBub3QgaW5zdGFuY2Ugb2YgTXlDdXJzb3IiKQoKY2xhc3MgUm93RmFjdG9yeVRlc3RzQmFja3dhcmRzQ29tcGF0KHVuaXR0ZXN0LlRlc3RDYXNlKToKICAgIGRlZiBzZXRVcChzZWxmKToKICAgICAgICBzZWxmLmNvbiA9IHNxbGl0ZS5jb25uZWN0KCI6bWVtb3J5OiIpCgogICAgZGVmIENoZWNrSXNQcm9kdWNlZEJ5RmFjdG9yeShzZWxmKToKICAgICAgICBjdXIgPSBzZWxmLmNvbi5jdXJzb3IoZmFjdG9yeT1NeUN1cnNvcikKICAgICAgICBjdXIuZXhlY3V0ZSgic2VsZWN0IDQrNSBhcyBmb28iKQogICAgICAgIHJvdyA9IGN1ci5mZXRjaG9uZSgpCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKGlzaW5zdGFuY2Uocm93LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpY3QpLAogICAgICAgICAgICAgICAgICAgICAgICAicm93IGlzIG5vdCBpbnN0YW5jZSBvZiBkaWN0IikKICAgICAgICBjdXIuY2xvc2UoKQoKICAgIGRlZiB0ZWFyRG93bihzZWxmKToKICAgICAgICBzZWxmLmNvbi5jbG9zZSgpCgpjbGFzcyBSb3dGYWN0b3J5VGVzdHModW5pdHRlc3QuVGVzdENhc2UpOgogICAgZGVmIHNldFVwKHNlbGYpOgogICAgICAgIHNlbGYuY29uID0gc3FsaXRlLmNvbm5lY3QoIjptZW1vcnk6IikKCiAgICBkZWYgQ2hlY2tDdXN0b21GYWN0b3J5KHNlbGYpOgogICAgICAgIHNlbGYuY29uLnJvd19mYWN0b3J5ID0gbGFtYmRhIGN1ciwgcm93OiBsaXN0KHJvdykKICAgICAgICByb3cgPSBzZWxmLmNvbi5leGVjdXRlKCJzZWxlY3QgMSwgMiIpLmZldGNob25lKCkKICAgICAgICBzZWxmLmZhaWxVbmxlc3MoaXNpbnN0YW5jZShyb3csCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdCksCiAgICAgICAgICAgICAgICAgICAgICAgICJyb3cgaXMgbm90IGluc3RhbmNlIG9mIGxpc3QiKQoKICAgIGRlZiBDaGVja1NxbGl0ZVJvd0luZGV4KHNlbGYpOgogICAgICAgIHNlbGYuY29uLnJvd19mYWN0b3J5ID0gc3FsaXRlLlJvdwogICAgICAgIHJvdyA9IHNlbGYuY29uLmV4ZWN1dGUoInNlbGVjdCAxIGFzIGEsIDIgYXMgYiIpLmZldGNob25lKCkKICAgICAgICBzZWxmLmZhaWxVbmxlc3MoaXNpbnN0YW5jZShyb3csCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3FsaXRlLlJvdyksCiAgICAgICAgICAgICAgICAgICAgICAgICJyb3cgaXMgbm90IGluc3RhbmNlIG9mIHNxbGl0ZS5Sb3ciKQoKICAgICAgICBjb2wxLCBjb2wyID0gcm93WyJhIl0sIHJvd1siYiJdCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKGNvbDEgPT0gMSwgImJ5IG5hbWU6IHdyb25nIHJlc3VsdCBmb3IgY29sdW1uICdhJyIpCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKGNvbDIgPT0gMiwgImJ5IG5hbWU6IHdyb25nIHJlc3VsdCBmb3IgY29sdW1uICdhJyIpCgogICAgICAgIGNvbDEsIGNvbDIgPSByb3dbIkEiXSwgcm93WyJCIl0KICAgICAgICBzZWxmLmZhaWxVbmxlc3MoY29sMSA9PSAxLCAiYnkgbmFtZTogd3JvbmcgcmVzdWx0IGZvciBjb2x1bW4gJ0EnIikKICAgICAgICBzZWxmLmZhaWxVbmxlc3MoY29sMiA9PSAyLCAiYnkgbmFtZTogd3JvbmcgcmVzdWx0IGZvciBjb2x1bW4gJ0InIikKCiAgICAgICAgY29sMSwgY29sMiA9IHJvd1swXSwgcm93WzFdCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKGNvbDEgPT0gMSwgImJ5IGluZGV4OiB3cm9uZyByZXN1bHQgZm9yIGNvbHVtbiAwIikKICAgICAgICBzZWxmLmZhaWxVbmxlc3MoY29sMiA9PSAyLCAiYnkgaW5kZXg6IHdyb25nIHJlc3VsdCBmb3IgY29sdW1uIDEiKQoKICAgIGRlZiBDaGVja1NxbGl0ZVJvd0l0ZXIoc2VsZik6CiAgICAgICAgIiIiQ2hlY2tzIGlmIHRoZSByb3cgb2JqZWN0IGlzIGl0ZXJhYmxlIiIiCiAgICAgICAgc2VsZi5jb24ucm93X2ZhY3RvcnkgPSBzcWxpdGUuUm93CiAgICAgICAgcm93ID0gc2VsZi5jb24uZXhlY3V0ZSgic2VsZWN0IDEgYXMgYSwgMiBhcyBiIikuZmV0Y2hvbmUoKQogICAgICAgIGZvciBjb2wgaW4gcm93OgogICAgICAgICAgICBwYXNzCgogICAgZGVmIENoZWNrU3FsaXRlUm93QXNUdXBsZShzZWxmKToKICAgICAgICAiIiJDaGVja3MgaWYgdGhlIHJvdyBvYmplY3QgY2FuIGJlIGNvbnZlcnRlZCB0byBhIHR1cGxlIiIiCiAgICAgICAgc2VsZi5jb24ucm93X2ZhY3RvcnkgPSBzcWxpdGUuUm93CiAgICAgICAgcm93ID0gc2VsZi5jb24uZXhlY3V0ZSgic2VsZWN0IDEgYXMgYSwgMiBhcyBiIikuZmV0Y2hvbmUoKQogICAgICAgIHQgPSB0dXBsZShyb3cpCgogICAgZGVmIENoZWNrU3FsaXRlUm93QXNEaWN0KHNlbGYpOgogICAgICAgICIiIkNoZWNrcyBpZiB0aGUgcm93IG9iamVjdCBjYW4gYmUgY29ycmVjdGx5IGNvbnZlcnRlZCB0byBhIGRpY3Rpb25hcnkiIiIKICAgICAgICBzZWxmLmNvbi5yb3dfZmFjdG9yeSA9IHNxbGl0ZS5Sb3cKICAgICAgICByb3cgPSBzZWxmLmNvbi5leGVjdXRlKCJzZWxlY3QgMSBhcyBhLCAyIGFzIGIiKS5mZXRjaG9uZSgpCiAgICAgICAgZCA9IGRpY3Qocm93KQogICAgICAgIHNlbGYuZmFpbFVubGVzc0VxdWFsKGRbImEiXSwgcm93WyJhIl0pCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzRXF1YWwoZFsiYiJdLCByb3dbImIiXSkKCiAgICBkZWYgQ2hlY2tTcWxpdGVSb3dIYXNoQ21wKHNlbGYpOgogICAgICAgICIiIkNoZWNrcyBpZiB0aGUgcm93IG9iamVjdCBjb21wYXJlcyBhbmQgaGFzaGVzIGNvcnJlY3RseSIiIgogICAgICAgIHNlbGYuY29uLnJvd19mYWN0b3J5ID0gc3FsaXRlLlJvdwogICAgICAgIHJvd18xID0gc2VsZi5jb24uZXhlY3V0ZSgic2VsZWN0IDEgYXMgYSwgMiBhcyBiIikuZmV0Y2hvbmUoKQogICAgICAgIHJvd18yID0gc2VsZi5jb24uZXhlY3V0ZSgic2VsZWN0IDEgYXMgYSwgMiBhcyBiIikuZmV0Y2hvbmUoKQogICAgICAgIHJvd18zID0gc2VsZi5jb24uZXhlY3V0ZSgic2VsZWN0IDEgYXMgYSwgMyBhcyBiIikuZmV0Y2hvbmUoKQoKICAgICAgICBzZWxmLmZhaWxVbmxlc3Mocm93XzEgPT0gcm93XzEpCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKHJvd18xID09IHJvd18yKQogICAgICAgIHNlbGYuZmFpbFVubGVzcyhyb3dfMiAhPSByb3dfMykKCiAgICAgICAgc2VsZi5mYWlsSWYocm93XzEgIT0gcm93XzEpCiAgICAgICAgc2VsZi5mYWlsSWYocm93XzEgIT0gcm93XzIpCiAgICAgICAgc2VsZi5mYWlsSWYocm93XzIgPT0gcm93XzMpCgogICAgICAgIHNlbGYuZmFpbFVubGVzc0VxdWFsKHJvd18xLCByb3dfMikKICAgICAgICBzZWxmLmZhaWxVbmxlc3NFcXVhbChoYXNoKHJvd18xKSwgaGFzaChyb3dfMikpCiAgICAgICAgc2VsZi5mYWlsSWZFcXVhbChyb3dfMSwgcm93XzMpCiAgICAgICAgc2VsZi5mYWlsSWZFcXVhbChoYXNoKHJvd18xKSwgaGFzaChyb3dfMykpCgogICAgZGVmIHRlYXJEb3duKHNlbGYpOgogICAgICAgIHNlbGYuY29uLmNsb3NlKCkKCmNsYXNzIFRleHRGYWN0b3J5VGVzdHModW5pdHRlc3QuVGVzdENhc2UpOgogICAgZGVmIHNldFVwKHNlbGYpOgogICAgICAgIHNlbGYuY29uID0gc3FsaXRlLmNvbm5lY3QoIjptZW1vcnk6IikKCiAgICBkZWYgQ2hlY2tVbmljb2RlKHNlbGYpOgogICAgICAgIGF1c3RyaWEgPSAi1nN0ZXJyZWljaCIKICAgICAgICByb3cgPSBzZWxmLmNvbi5leGVjdXRlKCJzZWxlY3QgPyIsIChhdXN0cmlhLCkpLmZldGNob25lKCkKICAgICAgICBzZWxmLmZhaWxVbmxlc3ModHlwZShyb3dbMF0pID09IHN0ciwgInR5cGUgb2Ygcm93WzBdIG11c3QgYmUgdW5pY29kZSIpCgogICAgZGVmIENoZWNrU3RyaW5nKHNlbGYpOgogICAgICAgIHNlbGYuY29uLnRleHRfZmFjdG9yeSA9IGJ5dGVzCiAgICAgICAgYXVzdHJpYSA9ICLWc3RlcnJlaWNoIgogICAgICAgIHJvdyA9IHNlbGYuY29uLmV4ZWN1dGUoInNlbGVjdCA/IiwgKGF1c3RyaWEsKSkuZmV0Y2hvbmUoKQogICAgICAgIHNlbGYuZmFpbFVubGVzcyh0eXBlKHJvd1swXSkgPT0gYnl0ZXMsICJ0eXBlIG9mIHJvd1swXSBtdXN0IGJlIGJ5dGVzIikKICAgICAgICBzZWxmLmZhaWxVbmxlc3Mocm93WzBdID09IGF1c3RyaWEuZW5jb2RlKCJ1dGYtOCIpLCAiY29sdW1uIG11c3QgZXF1YWwgb3JpZ2luYWwgZGF0YSBpbiBVVEYtOCIpCgogICAgZGVmIENoZWNrQ3VzdG9tKHNlbGYpOgogICAgICAgIHNlbGYuY29uLnRleHRfZmFjdG9yeSA9IGxhbWJkYSB4OiBzdHIoeCwgInV0Zi04IiwgImlnbm9yZSIpCiAgICAgICAgYXVzdHJpYSA9ICLWc3RlcnJlaWNoIgogICAgICAgIHJvdyA9IHNlbGYuY29uLmV4ZWN1dGUoInNlbGVjdCA/IiwgKGF1c3RyaWEsKSkuZmV0Y2hvbmUoKQogICAgICAgIHNlbGYuZmFpbFVubGVzcyh0eXBlKHJvd1swXSkgPT0gc3RyLCAidHlwZSBvZiByb3dbMF0gbXVzdCBiZSB1bmljb2RlIikKICAgICAgICBzZWxmLmZhaWxVbmxlc3Mocm93WzBdLmVuZHN3aXRoKCJyZWljaCIpLCAiY29sdW1uIG11c3QgY29udGFpbiBvcmlnaW5hbCBkYXRhIikKCiAgICBkZWYgQ2hlY2tPcHRpbWl6ZWRVbmljb2RlKHNlbGYpOgogICAgICAgIHNlbGYuY29uLnRleHRfZmFjdG9yeSA9IHNxbGl0ZS5PcHRpbWl6ZWRVbmljb2RlCiAgICAgICAgYXVzdHJpYSA9ICLWc3RlcnJlaWNoIgogICAgICAgIGdlcm1hbnkgPSAiRGV1dGNobGFuZCIKICAgICAgICBhX3JvdyA9IHNlbGYuY29uLmV4ZWN1dGUoInNlbGVjdCA/IiwgKGF1c3RyaWEsKSkuZmV0Y2hvbmUoKQogICAgICAgIGRfcm93ID0gc2VsZi5jb24uZXhlY3V0ZSgic2VsZWN0ID8iLCAoZ2VybWFueSwpKS5mZXRjaG9uZSgpCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKHR5cGUoYV9yb3dbMF0pID09IHN0ciwgInR5cGUgb2Ygbm9uLUFTQ0lJIHJvdyBtdXN0IGJlIHN0ciIpCiAgICAgICAgc2VsZi5mYWlsVW5sZXNzKHR5cGUoZF9yb3dbMF0pID09IHN0ciwgInR5cGUgb2YgQVNDSUktb25seSByb3cgbXVzdCBiZSBzdHIiKQoKICAgIGRlZiB0ZWFyRG93bihzZWxmKToKICAgICAgICBzZWxmLmNvbi5jbG9zZSgpCgpkZWYgc3VpdGUoKToKICAgIGNvbm5lY3Rpb25fc3VpdGUgPSB1bml0dGVzdC5tYWtlU3VpdGUoQ29ubmVjdGlvbkZhY3RvcnlUZXN0cywgIkNoZWNrIikKICAgIGN1cnNvcl9zdWl0ZSA9IHVuaXR0ZXN0Lm1ha2VTdWl0ZShDdXJzb3JGYWN0b3J5VGVzdHMsICJDaGVjayIpCiAgICByb3dfc3VpdGVfY29tcGF0ID0gdW5pdHRlc3QubWFrZVN1aXRlKFJvd0ZhY3RvcnlUZXN0c0JhY2t3YXJkc0NvbXBhdCwgIkNoZWNrIikKICAgIHJvd19zdWl0ZSA9IHVuaXR0ZXN0Lm1ha2VTdWl0ZShSb3dGYWN0b3J5VGVzdHMsICJDaGVjayIpCiAgICB0ZXh0X3N1aXRlID0gdW5pdHRlc3QubWFrZVN1aXRlKFRleHRGYWN0b3J5VGVzdHMsICJDaGVjayIpCiAgICByZXR1cm4gdW5pdHRlc3QuVGVzdFN1aXRlKChjb25uZWN0aW9uX3N1aXRlLCBjdXJzb3Jfc3VpdGUsIHJvd19zdWl0ZV9jb21wYXQsIHJvd19zdWl0ZSwgdGV4dF9zdWl0ZSkpCgpkZWYgdGVzdCgpOgogICAgcnVubmVyID0gdW5pdHRlc3QuVGV4dFRlc3RSdW5uZXIoKQogICAgcnVubmVyLnJ1bihzdWl0ZSgpKQoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHRlc3QoKQo=