Iy0qLSBjb2Rpbmc6IGlzby04ODU5LTEgLSotCiMgcHlzcWxpdGUyL3Rlc3QvcmVncmVzc2lvbi5weTogcHlzcWxpdGUgcmVncmVzc2lvbiB0ZXN0cwojCiMgQ29weXJpZ2h0IChDKSAyMDA2LTIwMDcgR2VyaGFyZCBI5HJpbmcgPGdoQGdoYWVyaW5nLmRlPgojCiMgVGhpcyBmaWxlIGlzIHBhcnQgb2YgcHlzcWxpdGUuCiMKIyBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkICdhcy1pcycsIHdpdGhvdXQgYW55IGV4cHJlc3Mgb3IgaW1wbGllZAojIHdhcnJhbnR5LiAgSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXMKIyBhcmlzaW5nIGZyb20gdGhlIHVzZSBvZiB0aGlzIHNvZnR3YXJlLgojCiMgUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsCiMgaW5jbHVkaW5nIGNvbW1lcmNpYWwgYXBwbGljYXRpb25zLCBhbmQgdG8gYWx0ZXIgaXQgYW5kIHJlZGlzdHJpYnV0ZSBpdAojIGZyZWVseSwgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIHJlc3RyaWN0aW9uczoKIwojIDEuIFRoZSBvcmlnaW4gb2YgdGhpcyBzb2Z0d2FyZSBtdXN0IG5vdCBiZSBtaXNyZXByZXNlbnRlZDsgeW91IG11c3Qgbm90CiMgICAgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmUKIyAgICBpbiBhIHByb2R1Y3QsIGFuIGFja25vd2xlZGdtZW50IGluIHRoZSBwcm9kdWN0IGRvY3VtZW50YXRpb24gd291bGQgYmUKIyAgICBhcHByZWNpYXRlZCBidXQgaXMgbm90IHJlcXVpcmVkLgojIDIuIEFsdGVyZWQgc291cmNlIHZlcnNpb25zIG11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaCwgYW5kIG11c3Qgbm90IGJlCiMgICAgbWlzcmVwcmVzZW50ZWQgYXMgYmVpbmcgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLgojIDMuIFRoaXMgbm90aWNlIG1heSBub3QgYmUgcmVtb3ZlZCBvciBhbHRlcmVkIGZyb20gYW55IHNvdXJjZSBkaXN0cmlidXRpb24uCgppbXBvcnQgZGF0ZXRpbWUKaW1wb3J0IHVuaXR0ZXN0CmltcG9ydCBzcWxpdGUzIGFzIHNxbGl0ZQppbXBvcnQgd2Vha3JlZgpmcm9tIHRlc3QgaW1wb3J0IHN1cHBvcnQKCmNsYXNzIFJlZ3Jlc3Npb25UZXN0cyh1bml0dGVzdC5UZXN0Q2FzZSk6CiAgICBkZWYgc2V0VXAoc2VsZik6CiAgICAgICAgc2VsZi5jb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiKQoKICAgIGRlZiB0ZWFyRG93bihzZWxmKToKICAgICAgICBzZWxmLmNvbi5jbG9zZSgpCgogICAgZGVmIENoZWNrUHJhZ21hVXNlclZlcnNpb24oc2VsZik6CiAgICAgICAgIyBUaGlzIHVzZWQgdG8gY3Jhc2ggcHlzcWxpdGUgYmVjYXVzZSB0aGlzIHByYWdtYSBjb21tYW5kIHJldHVybnMgTlVMTCBmb3IgdGhlIGNvbHVtbiBuYW1lCiAgICAgICAgY3VyID0gc2VsZi5jb24uY3Vyc29yKCkKICAgICAgICBjdXIuZXhlY3V0ZSgicHJhZ21hIHVzZXJfdmVyc2lvbiIpCgogICAgZGVmIENoZWNrUHJhZ21hU2NoZW1hVmVyc2lvbihzZWxmKToKICAgICAgICAjIFRoaXMgc3RpbGwgY3Jhc2hlZCBweXNxbGl0ZSA8PSAyLjIuMQogICAgICAgIGNvbiA9IHNxbGl0ZS5jb25uZWN0KCI6bWVtb3J5OiIsIGRldGVjdF90eXBlcz1zcWxpdGUuUEFSU0VfQ09MTkFNRVMpCiAgICAgICAgdHJ5OgogICAgICAgICAgICBjdXIgPSBzZWxmLmNvbi5jdXJzb3IoKQogICAgICAgICAgICBjdXIuZXhlY3V0ZSgicHJhZ21hIHNjaGVtYV92ZXJzaW9uIikKICAgICAgICBmaW5hbGx5OgogICAgICAgICAgICBjdXIuY2xvc2UoKQogICAgICAgICAgICBjb24uY2xvc2UoKQoKICAgIGRlZiBDaGVja1N0YXRlbWVudFJlc2V0KHNlbGYpOgogICAgICAgICMgcHlzcWxpdGUgMi4xLjAgdG8gMi4yLjAgaGF2ZSB0aGUgcHJvYmxlbSB0aGF0IG5vdCBhbGwgc3RhdGVtZW50cyBhcmUKICAgICAgICAjIHJlc2V0IGJlZm9yZSBhIHJvbGxiYWNrLCBidXQgb25seSB0aG9zZSB0aGF0IGFyZSBzdGlsbCBpbiB0aGUKICAgICAgICAjIHN0YXRlbWVudCBjYWNoZS4gVGhlIG90aGVycyBhcmUgbm90IGFjY2Vzc2libGUgZnJvbSB0aGUgY29ubmVjdGlvbiBvYmplY3QuCiAgICAgICAgY29uID0gc3FsaXRlLmNvbm5lY3QoIjptZW1vcnk6IiwgY2FjaGVkX3N0YXRlbWVudHM9NSkKICAgICAgICBjdXJzb3JzID0gW2Nvbi5jdXJzb3IoKSBmb3IgeCBpbiB4cmFuZ2UoNSldCiAgICAgICAgY3Vyc29yc1swXS5leGVjdXRlKCJjcmVhdGUgdGFibGUgdGVzdCh4KSIpCiAgICAgICAgZm9yIGkgaW4gcmFuZ2UoMTApOgogICAgICAgICAgICBjdXJzb3JzWzBdLmV4ZWN1dGVtYW55KCJpbnNlcnQgaW50byB0ZXN0KHgpIHZhbHVlcyAoPykiLCBbKHgsKSBmb3IgeCBpbiB4cmFuZ2UoMTApXSkKCiAgICAgICAgZm9yIGkgaW4gcmFuZ2UoNSk6CiAgICAgICAgICAgIGN1cnNvcnNbaV0uZXhlY3V0ZSgiICIgKiBpICsgInNlbGVjdCB4IGZyb20gdGVzdCIpCgogICAgICAgIGNvbi5yb2xsYmFjaygpCgogICAgZGVmIENoZWNrQ29sdW1uTmFtZVdpdGhTcGFjZXMoc2VsZik6CiAgICAgICAgY3VyID0gc2VsZi5jb24uY3Vyc29yKCkKICAgICAgICBjdXIuZXhlY3V0ZSgnc2VsZWN0IDEgYXMgImZvbyBiYXIgW2RhdGV0aW1lXSInKQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoY3VyLmRlc2NyaXB0aW9uWzBdWzBdLCAiZm9vIGJhciIpCgogICAgICAgIGN1ci5leGVjdXRlKCdzZWxlY3QgMSBhcyAiZm9vIGJheiInKQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoY3VyLmRlc2NyaXB0aW9uWzBdWzBdLCAiZm9vIGJheiIpCgogICAgZGVmIENoZWNrU3RhdGVtZW50RmluYWxpemF0aW9uT25DbG9zZURiKHNlbGYpOgogICAgICAgICMgcHlzcWxpdGUgdmVyc2lvbnMgPD0gMi4zLjMgb25seSBmaW5hbGl6ZWQgc3RhdGVtZW50cyBpbiB0aGUgc3RhdGVtZW50CiAgICAgICAgIyBjYWNoZSB3aGVuIGNsb3NpbmcgdGhlIGRhdGFiYXNlLiBzdGF0ZW1lbnRzIHRoYXQgd2VyZSBzdGlsbAogICAgICAgICMgcmVmZXJlbmNlZCBpbiBjdXJzb3JzIHdlcmVuJ3QgY2xvc2VkIGFuZCBjb3VsZCBwcm92b2tlICIKICAgICAgICAjICJPcGVyYXRpb25hbEVycm9yOiBVbmFibGUgdG8gY2xvc2UgZHVlIHRvIHVuZmluYWxpc2VkIHN0YXRlbWVudHMiLgogICAgICAgIGNvbiA9IHNxbGl0ZS5jb25uZWN0KCI6bWVtb3J5OiIpCiAgICAgICAgY3Vyc29ycyA9IFtdCiAgICAgICAgIyBkZWZhdWx0IHN0YXRlbWVudCBjYWNoZSBzaXplIGlzIDEwMAogICAgICAgIGZvciBpIGluIHJhbmdlKDEwNSk6CiAgICAgICAgICAgIGN1ciA9IGNvbi5jdXJzb3IoKQogICAgICAgICAgICBjdXJzb3JzLmFwcGVuZChjdXIpCiAgICAgICAgICAgIGN1ci5leGVjdXRlKCJzZWxlY3QgMSB4IHVuaW9uIHNlbGVjdCAiICsgc3RyKGkpKQogICAgICAgIGNvbi5jbG9zZSgpCgogICAgZGVmIENoZWNrT25Db25mbGljdFJvbGxiYWNrKHNlbGYpOgogICAgICAgIGlmIHNxbGl0ZS5zcWxpdGVfdmVyc2lvbl9pbmZvIDwgKDMsIDIsIDIpOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBjb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiKQogICAgICAgIGNvbi5leGVjdXRlKCJjcmVhdGUgdGFibGUgZm9vKHgsIHVuaXF1ZSh4KSBvbiBjb25mbGljdCByb2xsYmFjaykiKQogICAgICAgIGNvbi5leGVjdXRlKCJpbnNlcnQgaW50byBmb28oeCkgdmFsdWVzICgxKSIpCiAgICAgICAgdHJ5OgogICAgICAgICAgICBjb24uZXhlY3V0ZSgiaW5zZXJ0IGludG8gZm9vKHgpIHZhbHVlcyAoMSkiKQogICAgICAgIGV4Y2VwdCBzcWxpdGUuRGF0YWJhc2VFcnJvcjoKICAgICAgICAgICAgcGFzcwogICAgICAgIGNvbi5leGVjdXRlKCJpbnNlcnQgaW50byBmb28oeCkgdmFsdWVzICgyKSIpCiAgICAgICAgdHJ5OgogICAgICAgICAgICBjb24uY29tbWl0KCkKICAgICAgICBleGNlcHQgc3FsaXRlLk9wZXJhdGlvbmFsRXJyb3I6CiAgICAgICAgICAgIHNlbGYuZmFpbCgicHlzcWxpdGUga25ldyBub3RoaW5nIGFib3V0IHRoZSBpbXBsaWNpdCBST0xMQkFDSyIpCgogICAgZGVmIENoZWNrV29ya2Fyb3VuZEZvckJ1Z2d5U3FsaXRlVHJhbnNmZXJCaW5kaW5ncyhzZWxmKToKICAgICAgICAiIiIKICAgICAgICBweXNxbGl0ZSB3b3VsZCBjcmFzaCB3aXRoIG9sZGVyIFNRTGl0ZSB2ZXJzaW9ucyB1bmxlc3MKICAgICAgICBhIHdvcmthcm91bmQgaXMgaW1wbGVtZW50ZWQuCiAgICAgICAgIiIiCiAgICAgICAgc2VsZi5jb24uZXhlY3V0ZSgiY3JlYXRlIHRhYmxlIGZvbyhiYXIpIikKICAgICAgICBzZWxmLmNvbi5leGVjdXRlKCJkcm9wIHRhYmxlIGZvbyIpCiAgICAgICAgc2VsZi5jb24uZXhlY3V0ZSgiY3JlYXRlIHRhYmxlIGZvbyhiYXIpIikKCiAgICBkZWYgQ2hlY2tFbXB0eVN0YXRlbWVudChzZWxmKToKICAgICAgICAiIiIKICAgICAgICBweXNxbGl0ZSB1c2VkIHRvIHNlZ2ZhdWx0IHdpdGggU1FMaXRlIHZlcnNpb25zIDMuNS54LiBUaGVzZSByZXR1cm4gTlVMTAogICAgICAgIGZvciAibm8tb3BlcmF0aW9uIiBzdGF0ZW1lbnRzCiAgICAgICAgIiIiCiAgICAgICAgc2VsZi5jb24uZXhlY3V0ZSgiIikKCiAgICBkZWYgQ2hlY2tVbmljb2RlQ29ubmVjdChzZWxmKToKICAgICAgICAiIiIKICAgICAgICBXaXRoIHB5c3FsaXRlIDIuNC4wIHlvdSBuZWVkZWQgdG8gdXNlIGEgc3RyaW5nIG9yIGFuIEFQU1cgY29ubmVjdGlvbgogICAgICAgIG9iamVjdCBmb3Igb3BlbmluZyBkYXRhYmFzZSBjb25uZWN0aW9ucy4KCiAgICAgICAgRm9ybWVybHksIGJvdGggYnl0ZXN0cmluZ3MgYW5kIHVuaWNvZGUgc3RyaW5ncyB1c2VkIHRvIHdvcmsuCgogICAgICAgIExldCdzIG1ha2Ugc3VyZSB1bmljb2RlIHN0cmluZ3Mgd29yayBpbiB0aGUgZnV0dXJlLgogICAgICAgICIiIgogICAgICAgIGNvbiA9IHNxbGl0ZS5jb25uZWN0KHUiOm1lbW9yeToiKQogICAgICAgIGNvbi5jbG9zZSgpCgogICAgZGVmIENoZWNrVHlwZU1hcFVzYWdlKHNlbGYpOgogICAgICAgICIiIgogICAgICAgIHB5c3FsaXRlIHVudGlsIDIuNC4xIGRpZCBub3QgcmVidWlsZCB0aGUgcm93X2Nhc3RfbWFwIHdoZW4gcmVjb21waWxpbmcKICAgICAgICBhIHN0YXRlbWVudC4gVGhpcyB0ZXN0IGV4aGliaXRzIHRoZSBwcm9ibGVtLgogICAgICAgICIiIgogICAgICAgIFNFTEVDVCA9ICJzZWxlY3QgKiBmcm9tIGZvbyIKICAgICAgICBjb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiLGRldGVjdF90eXBlcz1zcWxpdGUuUEFSU0VfREVDTFRZUEVTKQogICAgICAgIGNvbi5leGVjdXRlKCJjcmVhdGUgdGFibGUgZm9vKGJhciB0aW1lc3RhbXApIikKICAgICAgICBjb24uZXhlY3V0ZSgiaW5zZXJ0IGludG8gZm9vKGJhcikgdmFsdWVzICg/KSIsIChkYXRldGltZS5kYXRldGltZS5ub3coKSwpKQogICAgICAgIGNvbi5leGVjdXRlKFNFTEVDVCkKICAgICAgICBjb24uZXhlY3V0ZSgiZHJvcCB0YWJsZSBmb28iKQogICAgICAgIGNvbi5leGVjdXRlKCJjcmVhdGUgdGFibGUgZm9vKGJhciBpbnRlZ2VyKSIpCiAgICAgICAgY29uLmV4ZWN1dGUoImluc2VydCBpbnRvIGZvbyhiYXIpIHZhbHVlcyAoNSkiKQogICAgICAgIGNvbi5leGVjdXRlKFNFTEVDVCkKCiAgICBkZWYgQ2hlY2tSZWdpc3RlckFkYXB0ZXIoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgU2VlIGlzc3VlIDMzMTIuCiAgICAgICAgIiIiCiAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoVHlwZUVycm9yLCBzcWxpdGUucmVnaXN0ZXJfYWRhcHRlciwge30sIE5vbmUpCgogICAgZGVmIENoZWNrU2V0SXNvbGF0aW9uTGV2ZWwoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgU2VlIGlzc3VlIDMzMTIuCiAgICAgICAgIiIiCiAgICAgICAgY29uID0gc3FsaXRlLmNvbm5lY3QoIjptZW1vcnk6IikKICAgICAgICBzZWxmLmFzc2VydFJhaXNlcyhVbmljb2RlRW5jb2RlRXJyb3IsIHNldGF0dHIsIGNvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAiaXNvbGF0aW9uX2xldmVsIiwgdSJceGU5IikKCiAgICBkZWYgQ2hlY2tDdXJzb3JDb25zdHJ1Y3RvckNhbGxDaGVjayhzZWxmKToKICAgICAgICAiIiIKICAgICAgICBWZXJpZmllcyB0aGF0IGN1cnNvciBtZXRob2RzIGNoZWNrIHdoZXRoZXIgYmFzZSBjbGFzcyBfX2luaXRfXyB3YXMKICAgICAgICBjYWxsZWQuCiAgICAgICAgIiIiCiAgICAgICAgY2xhc3MgQ3Vyc29yKHNxbGl0ZS5DdXJzb3IpOgogICAgICAgICAgICBkZWYgX19pbml0X18oc2VsZiwgY29uKToKICAgICAgICAgICAgICAgIHBhc3MKCiAgICAgICAgY29uID0gc3FsaXRlLmNvbm5lY3QoIjptZW1vcnk6IikKICAgICAgICBjdXIgPSBDdXJzb3IoY29uKQogICAgICAgIHRyeToKICAgICAgICAgICAgY3VyLmV4ZWN1dGUoInNlbGVjdCA0KzUiKS5mZXRjaGFsbCgpCiAgICAgICAgICAgIHNlbGYuZmFpbCgic2hvdWxkIGhhdmUgcmFpc2VkIFByb2dyYW1taW5nRXJyb3IiKQogICAgICAgIGV4Y2VwdCBzcWxpdGUuUHJvZ3JhbW1pbmdFcnJvcjoKICAgICAgICAgICAgcGFzcwogICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgc2VsZi5mYWlsKCJzaG91bGQgaGF2ZSByYWlzZWQgUHJvZ3JhbW1pbmdFcnJvciIpCiAgICAgICAgd2l0aCBzZWxmLmFzc2VydFJhaXNlc1JlZ2V4cChzcWxpdGUuUHJvZ3JhbW1pbmdFcnJvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHInXkJhc2UgQ3Vyc29yXC5fX2luaXRfXyBub3QgY2FsbGVkXC4kJyk6CiAgICAgICAgICAgIGN1ci5jbG9zZSgpCgogICAgZGVmIENoZWNrQ29ubmVjdGlvbkNvbnN0cnVjdG9yQ2FsbENoZWNrKHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFZlcmlmaWVzIHRoYXQgY29ubmVjdGlvbiBtZXRob2RzIGNoZWNrIHdoZXRoZXIgYmFzZSBjbGFzcyBfX2luaXRfXyB3YXMKICAgICAgICBjYWxsZWQuCiAgICAgICAgIiIiCiAgICAgICAgY2xhc3MgQ29ubmVjdGlvbihzcWxpdGUuQ29ubmVjdGlvbik6CiAgICAgICAgICAgIGRlZiBfX2luaXRfXyhzZWxmLCBuYW1lKToKICAgICAgICAgICAgICAgIHBhc3MKCiAgICAgICAgY29uID0gQ29ubmVjdGlvbigiOm1lbW9yeToiKQogICAgICAgIHRyeToKICAgICAgICAgICAgY3VyID0gY29uLmN1cnNvcigpCiAgICAgICAgICAgIHNlbGYuZmFpbCgic2hvdWxkIGhhdmUgcmFpc2VkIFByb2dyYW1taW5nRXJyb3IiKQogICAgICAgIGV4Y2VwdCBzcWxpdGUuUHJvZ3JhbW1pbmdFcnJvcjoKICAgICAgICAgICAgcGFzcwogICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgc2VsZi5mYWlsKCJzaG91bGQgaGF2ZSByYWlzZWQgUHJvZ3JhbW1pbmdFcnJvciIpCgogICAgZGVmIENoZWNrQ3Vyc29yUmVnaXN0cmF0aW9uKHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFZlcmlmaWVzIHRoYXQgc3ViY2xhc3NlZCBjdXJzb3IgY2xhc3NlcyBhcmUgY29ycmVjdGx5IHJlZ2lzdGVyZWQgd2l0aAogICAgICAgIHRoZSBjb25uZWN0aW9uIG9iamVjdCwgdG9vLiAgKGZldGNoLWFjcm9zcy1yb2xsYmFjayBwcm9ibGVtKQogICAgICAgICIiIgogICAgICAgIGNsYXNzIENvbm5lY3Rpb24oc3FsaXRlLkNvbm5lY3Rpb24pOgogICAgICAgICAgICBkZWYgY3Vyc29yKHNlbGYpOgogICAgICAgICAgICAgICAgcmV0dXJuIEN1cnNvcihzZWxmKQoKICAgICAgICBjbGFzcyBDdXJzb3Ioc3FsaXRlLkN1cnNvcik6CiAgICAgICAgICAgIGRlZiBfX2luaXRfXyhzZWxmLCBjb24pOgogICAgICAgICAgICAgICAgc3FsaXRlLkN1cnNvci5fX2luaXRfXyhzZWxmLCBjb24pCgogICAgICAgIGNvbiA9IENvbm5lY3Rpb24oIjptZW1vcnk6IikKICAgICAgICBjdXIgPSBjb24uY3Vyc29yKCkKICAgICAgICBjdXIuZXhlY3V0ZSgiY3JlYXRlIHRhYmxlIGZvbyh4KSIpCiAgICAgICAgY3VyLmV4ZWN1dGVtYW55KCJpbnNlcnQgaW50byBmb28oeCkgdmFsdWVzICg/KSIsIFsoMywpLCAoNCwpLCAoNSwpXSkKICAgICAgICBjdXIuZXhlY3V0ZSgic2VsZWN0IHggZnJvbSBmb28iKQogICAgICAgIGNvbi5yb2xsYmFjaygpCiAgICAgICAgdHJ5OgogICAgICAgICAgICBjdXIuZmV0Y2hhbGwoKQogICAgICAgICAgICBzZWxmLmZhaWwoInNob3VsZCBoYXZlIHJhaXNlZCBJbnRlcmZhY2VFcnJvciIpCiAgICAgICAgZXhjZXB0IHNxbGl0ZS5JbnRlcmZhY2VFcnJvcjoKICAgICAgICAgICAgcGFzcwogICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgc2VsZi5mYWlsKCJzaG91bGQgaGF2ZSByYWlzZWQgSW50ZXJmYWNlRXJyb3IiKQoKICAgIGRlZiBDaGVja0F1dG9Db21taXQoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgVmVyaWZpZXMgdGhhdCBjcmVhdGluZyBhIGNvbm5lY3Rpb24gaW4gYXV0b2NvbW1pdCBtb2RlIHdvcmtzLgogICAgICAgIDIuNS4zIGludHJvZHVjZWQgYSByZWdyZXNzaW9uIHNvIHRoYXQgdGhlc2UgY291bGQgbm8gbG9uZ2VyCiAgICAgICAgYmUgY3JlYXRlZC4KICAgICAgICAiIiIKICAgICAgICBjb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiLCBpc29sYXRpb25fbGV2ZWw9Tm9uZSkKCiAgICBkZWYgQ2hlY2tQcmFnbWFBdXRvY29tbWl0KHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFZlcmlmaWVzIHRoYXQgcnVubmluZyBhIFBSQUdNQSBzdGF0ZW1lbnQgdGhhdCBkb2VzIGFuIGF1dG9jb21taXQgZG9lcwogICAgICAgIHdvcmsuIFRoaXMgZGlkIG5vdCB3b3JrIGluIDIuNS4zLzIuNS40LgogICAgICAgICIiIgogICAgICAgIGN1ciA9IHNlbGYuY29uLmN1cnNvcigpCiAgICAgICAgY3VyLmV4ZWN1dGUoImNyZWF0ZSB0YWJsZSBmb28oYmFyKSIpCiAgICAgICAgY3VyLmV4ZWN1dGUoImluc2VydCBpbnRvIGZvbyhiYXIpIHZhbHVlcyAoNSkiKQoKICAgICAgICBjdXIuZXhlY3V0ZSgicHJhZ21hIHBhZ2Vfc2l6ZSIpCiAgICAgICAgcm93ID0gY3VyLmZldGNob25lKCkKCiAgICBkZWYgQ2hlY2tTZXREaWN0KHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFNlZSBodHRwOi8vYnVncy5weXRob24ub3JnL2lzc3VlNzQ3OAoKICAgICAgICBJdCB3YXMgcG9zc2libGUgdG8gc3VjY2Vzc2Z1bGx5IHJlZ2lzdGVyIGNhbGxiYWNrcyB0aGF0IGNvdWxkIG5vdCBiZQogICAgICAgIGhhc2hlZC4gUmV0dXJuIGNvZGVzIG9mIFB5RGljdF9TZXRJdGVtIHdlcmUgbm90IGNoZWNrZWQgcHJvcGVybHkuCiAgICAgICAgIiIiCiAgICAgICAgY2xhc3MgTm90SGFzaGFibGU6CiAgICAgICAgICAgIGRlZiBfX2NhbGxfXyhzZWxmLCAqYXJncywgKiprdyk6CiAgICAgICAgICAgICAgICBwYXNzCiAgICAgICAgICAgIGRlZiBfX2hhc2hfXyhzZWxmKToKICAgICAgICAgICAgICAgIHJhaXNlIFR5cGVFcnJvcigpCiAgICAgICAgdmFyID0gTm90SGFzaGFibGUoKQogICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKFR5cGVFcnJvciwgc2VsZi5jb24uY3JlYXRlX2Z1bmN0aW9uLCB2YXIpCiAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoVHlwZUVycm9yLCBzZWxmLmNvbi5jcmVhdGVfYWdncmVnYXRlLCB2YXIpCiAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoVHlwZUVycm9yLCBzZWxmLmNvbi5zZXRfYXV0aG9yaXplciwgdmFyKQogICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKFR5cGVFcnJvciwgc2VsZi5jb24uc2V0X3Byb2dyZXNzX2hhbmRsZXIsIHZhcikKCiAgICBkZWYgQ2hlY2tDb25uZWN0aW9uQ2FsbChzZWxmKToKICAgICAgICAiIiIKICAgICAgICBDYWxsIGEgY29ubmVjdGlvbiB3aXRoIGEgbm9uLXN0cmluZyBTUUwgcmVxdWVzdDogY2hlY2sgZXJyb3IgaGFuZGxpbmcKICAgICAgICBvZiB0aGUgc3RhdGVtZW50IGNvbnN0cnVjdG9yLgogICAgICAgICIiIgogICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKHNxbGl0ZS5XYXJuaW5nLCBzZWxmLmNvbiwgMSkKCiAgICBkZWYgQ2hlY2tSZWN1cnNpdmVDdXJzb3JVc2Uoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgaHR0cDovL2J1Z3MucHl0aG9uLm9yZy9pc3N1ZTEwODExCgogICAgICAgIFJlY3Vyc2l2ZWx5IHVzaW5nIGEgY3Vyc29yLCBzdWNoIGFzIHdoZW4gcmV1c2luZyBpdCBmcm9tIGEgZ2VuZXJhdG9yIGxlZCB0byBzZWdmYXVsdHMuCiAgICAgICAgTm93IHdlIGNhdGNoIHJlY3Vyc2l2ZSBjdXJzb3IgdXNhZ2UgYW5kIHJhaXNlIGEgUHJvZ3JhbW1pbmdFcnJvci4KICAgICAgICAiIiIKICAgICAgICBjb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiKQoKICAgICAgICBjdXIgPSBjb24uY3Vyc29yKCkKICAgICAgICBjdXIuZXhlY3V0ZSgiY3JlYXRlIHRhYmxlIGEgKGJhcikiKQogICAgICAgIGN1ci5leGVjdXRlKCJjcmVhdGUgdGFibGUgYiAoYmF6KSIpCgogICAgICAgIGRlZiBmb28oKToKICAgICAgICAgICAgY3VyLmV4ZWN1dGUoImluc2VydCBpbnRvIGEgKGJhcikgdmFsdWVzICg/KSIsICgxLCkpCiAgICAgICAgICAgIHlpZWxkIDEKCiAgICAgICAgd2l0aCBzZWxmLmFzc2VydFJhaXNlcyhzcWxpdGUuUHJvZ3JhbW1pbmdFcnJvcik6CiAgICAgICAgICAgIGN1ci5leGVjdXRlbWFueSgiaW5zZXJ0IGludG8gYiAoYmF6KSB2YWx1ZXMgKD8pIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoaSwpIGZvciBpIGluIGZvbygpKSkKCiAgICBkZWYgQ2hlY2tDb252ZXJ0VGltZXN0YW1wTWljcm9zZWNvbmRQYWRkaW5nKHNlbGYpOgogICAgICAgICIiIgogICAgICAgIGh0dHA6Ly9idWdzLnB5dGhvbi5vcmcvaXNzdWUxNDcyMAoKICAgICAgICBUaGUgbWljcm9zZWNvbmQgcGFyc2luZyBvZiBjb252ZXJ0X3RpbWVzdGFtcCgpIHNob3VsZCBwYWQgd2l0aCB6ZXJvcywKICAgICAgICBzaW5jZSB0aGUgbWljcm9zZWNvbmQgc3RyaW5nICI0NTYiIGFjdHVhbGx5IHJlcHJlc2VudHMgIjQ1NjAwMCIuCiAgICAgICAgIiIiCgogICAgICAgIGNvbiA9IHNxbGl0ZS5jb25uZWN0KCI6bWVtb3J5OiIsIGRldGVjdF90eXBlcz1zcWxpdGUuUEFSU0VfREVDTFRZUEVTKQogICAgICAgIGN1ciA9IGNvbi5jdXJzb3IoKQogICAgICAgIGN1ci5leGVjdXRlKCJDUkVBVEUgVEFCTEUgdCAoeCBUSU1FU1RBTVApIikKCiAgICAgICAgIyBNaWNyb3NlY29uZHMgc2hvdWxkIGJlIDQ1NjAwMAogICAgICAgIGN1ci5leGVjdXRlKCJJTlNFUlQgSU5UTyB0ICh4KSBWQUxVRVMgKCcyMDEyLTA0LTA0IDE1OjA2OjAwLjQ1NicpIikKCiAgICAgICAgIyBNaWNyb3NlY29uZHMgc2hvdWxkIGJlIHRydW5jYXRlZCB0byAxMjM0NTYKICAgICAgICBjdXIuZXhlY3V0ZSgiSU5TRVJUIElOVE8gdCAoeCkgVkFMVUVTICgnMjAxMi0wNC0wNCAxNTowNjowMC4xMjM0NTY3ODknKSIpCgogICAgICAgIGN1ci5leGVjdXRlKCJTRUxFQ1QgKiBGUk9NIHQiKQogICAgICAgIHZhbHVlcyA9IFt4WzBdIGZvciB4IGluIGN1ci5mZXRjaGFsbCgpXQoKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKHZhbHVlcywgWwogICAgICAgICAgICBkYXRldGltZS5kYXRldGltZSgyMDEyLCA0LCA0LCAxNSwgNiwgMCwgNDU2MDAwKSwKICAgICAgICAgICAgZGF0ZXRpbWUuZGF0ZXRpbWUoMjAxMiwgNCwgNCwgMTUsIDYsIDAsIDEyMzQ1NiksCiAgICAgICAgXSkKCiAgICBkZWYgQ2hlY2tJbnZhbGlkSXNvbGF0aW9uTGV2ZWxUeXBlKHNlbGYpOgogICAgICAgICMgaXNvbGF0aW9uIGxldmVsIGlzIGEgc3RyaW5nLCBub3QgYW4gaW50ZWdlcgogICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKFR5cGVFcnJvciwKICAgICAgICAgICAgICAgICAgICAgICAgICBzcWxpdGUuY29ubmVjdCwgIjptZW1vcnk6IiwgaXNvbGF0aW9uX2xldmVsPTEyMykKCgogICAgZGVmIENoZWNrTnVsbENoYXJhY3RlcihzZWxmKToKICAgICAgICAjIElzc3VlICMyMTE0NwogICAgICAgIGNvbiA9IHNxbGl0ZS5jb25uZWN0KCI6bWVtb3J5OiIpCiAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoVmFsdWVFcnJvciwgY29uLCAiXDBzZWxlY3QgMSIpCiAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoVmFsdWVFcnJvciwgY29uLCAic2VsZWN0IDFcMCIpCiAgICAgICAgY3VyID0gY29uLmN1cnNvcigpCiAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoVmFsdWVFcnJvciwgY3VyLmV4ZWN1dGUsICIgXDBzZWxlY3QgMiIpCiAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoVmFsdWVFcnJvciwgY3VyLmV4ZWN1dGUsICJzZWxlY3QgMlwwIikKCiAgICBkZWYgQ2hlY2tDb21taXRDdXJzb3JSZXNldChzZWxmKToKICAgICAgICAiIiIKICAgICAgICBDb25uZWN0aW9uLmNvbW1pdCgpIGRpZCByZXNldCBjdXJzb3JzLCB3aGljaCBtYWRlIHNxbGl0ZTMKICAgICAgICB0byByZXR1cm4gcm93cyBtdWx0aXBsZSB0aW1lcyB3aGVuIGZldGNoZWQgZnJvbSBjdXJzb3JzCiAgICAgICAgYWZ0ZXIgY29tbWl0LiBTZWUgaXNzdWVzIDEwNTEzIGFuZCAyMzEyOSBmb3IgZGV0YWlscy4KICAgICAgICAiIiIKICAgICAgICBjb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiKQogICAgICAgIGNvbi5leGVjdXRlc2NyaXB0KCIiIgogICAgICAgIGNyZWF0ZSB0YWJsZSB0KGMpOwogICAgICAgIGNyZWF0ZSB0YWJsZSB0MihjKTsKICAgICAgICBpbnNlcnQgaW50byB0IHZhbHVlcygwKTsKICAgICAgICBpbnNlcnQgaW50byB0IHZhbHVlcygxKTsKICAgICAgICBpbnNlcnQgaW50byB0IHZhbHVlcygyKTsKICAgICAgICAiIiIpCgogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoY29uLmlzb2xhdGlvbl9sZXZlbCwgIiIpCgogICAgICAgIGNvdW50ZXIgPSAwCiAgICAgICAgZm9yIGksIHJvdyBpbiBlbnVtZXJhdGUoY29uLmV4ZWN1dGUoInNlbGVjdCBjIGZyb20gdCIpKToKICAgICAgICAgICAgY29uLmV4ZWN1dGUoImluc2VydCBpbnRvIHQyKGMpIHZhbHVlcyAoPykiLCAoaSwpKQogICAgICAgICAgICBjb24uY29tbWl0KCkKICAgICAgICAgICAgaWYgY291bnRlciA9PSAwOgogICAgICAgICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChyb3dbMF0sIDApCiAgICAgICAgICAgIGVsaWYgY291bnRlciA9PSAxOgogICAgICAgICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChyb3dbMF0sIDEpCiAgICAgICAgICAgIGVsaWYgY291bnRlciA9PSAyOgogICAgICAgICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChyb3dbMF0sIDIpCiAgICAgICAgICAgIGNvdW50ZXIgKz0gMQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoY291bnRlciwgMywgInNob3VsZCBoYXZlIHJldHVybmVkIGV4YWN0bHkgdGhyZWUgcm93cyIpCgogICAgZGVmIENoZWNrQnBvMzE3NzAoc2VsZik6CiAgICAgICAgIiIiCiAgICAgICAgVGhlIGludGVycHJldGVyIHNob3VsZG4ndCBjcmFzaCBpbiBjYXNlIEN1cnNvci5fX2luaXRfXygpIGlzIGNhbGxlZAogICAgICAgIG1vcmUgdGhhbiBvbmNlLgogICAgICAgICIiIgogICAgICAgIGRlZiBjYWxsYmFjaygqYXJncyk6CiAgICAgICAgICAgIHBhc3MKICAgICAgICBjb24gPSBzcWxpdGUuY29ubmVjdCgiOm1lbW9yeToiKQogICAgICAgIGN1ciA9IHNxbGl0ZS5DdXJzb3IoY29uKQogICAgICAgIHJlZiA9IHdlYWtyZWYucmVmKGN1ciwgY2FsbGJhY2spCiAgICAgICAgY3VyLl9faW5pdF9fKGNvbikKICAgICAgICBkZWwgY3VyCiAgICAgICAgIyBUaGUgaW50ZXJwcmV0ZXIgc2hvdWxkbid0IGNyYXNoIHdoZW4gcmVmIGlzIGNvbGxlY3RlZC4KICAgICAgICBkZWwgcmVmCiAgICAgICAgc3VwcG9ydC5nY19jb2xsZWN0KCkKCgpkZWYgc3VpdGUoKToKICAgIHJlZ3Jlc3Npb25fc3VpdGUgPSB1bml0dGVzdC5tYWtlU3VpdGUoUmVncmVzc2lvblRlc3RzLCAiQ2hlY2siKQogICAgcmV0dXJuIHVuaXR0ZXN0LlRlc3RTdWl0ZSgocmVncmVzc2lvbl9zdWl0ZSwpKQoKZGVmIHRlc3QoKToKICAgIHJ1bm5lciA9IHVuaXR0ZXN0LlRleHRUZXN0UnVubmVyKCkKICAgIHJ1bm5lci5ydW4oc3VpdGUoKSkKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICB0ZXN0KCkK