cGFja2FnZSBqdW5pdC5mcmFtZXdvcms7CgppbXBvcnQgamF2YS51dGlsLlZlY3RvcjsKaW1wb3J0IGphdmEudXRpbC5FbnVtZXJhdGlvbjsKaW1wb3J0IGphdmEuaW8uUHJpbnRXcml0ZXI7CmltcG9ydCBqYXZhLmlvLlN0cmluZ1dyaXRlcjsKaW1wb3J0IGphdmEubGFuZy5yZWZsZWN0Lio7CmltcG9ydCBqYXZhLmxhbmcucmVmbGVjdC5Db25zdHJ1Y3RvcjsKCi8qKgogKiBBIDxjb2RlPlRlc3RTdWl0ZTwvY29kZT4gaXMgYSA8Y29kZT5Db21wb3NpdGU8L2NvZGU+IG9mIFRlc3RzLgogKiBJdCBydW5zIGEgY29sbGVjdGlvbiBvZiB0ZXN0IGNhc2VzLiBIZXJlIGlzIGFuIGV4YW1wbGUgdXNpbmcKICogdGhlIGR5bmFtaWMgdGVzdCBkZWZpbml0aW9uLgogKiA8cHJlPgogKiBUZXN0U3VpdGUgc3VpdGU9IG5ldyBUZXN0U3VpdGUoKTsKICogc3VpdGUuYWRkVGVzdChuZXcgTWF0aFRlc3QoInRlc3RBZGQiKSk7CiAqIHN1aXRlLmFkZFRlc3QobmV3IE1hdGhUZXN0KCJ0ZXN0RGl2aWRlQnlaZXJvIikpOwogKiA8L3ByZT4KICogQWx0ZXJuYXRpdmVseSwgYSBUZXN0U3VpdGUgY2FuIGV4dHJhY3QgdGhlIHRlc3RzIHRvIGJlIHJ1biBhdXRvbWF0aWNhbGx5LgogKiBUbyBkbyBzbyB5b3UgcGFzcyB0aGUgY2xhc3Mgb2YgeW91ciBUZXN0Q2FzZSBjbGFzcyB0byB0aGUKICogVGVzdFN1aXRlIGNvbnN0cnVjdG9yLgogKiA8cHJlPgogKiBUZXN0U3VpdGUgc3VpdGU9IG5ldyBUZXN0U3VpdGUoTWF0aFRlc3QuY2xhc3MpOwogKiA8L3ByZT4KICogVGhpcyBjb25zdHJ1Y3RvciBjcmVhdGVzIGEgc3VpdGUgd2l0aCBhbGwgdGhlIG1ldGhvZHMKICogc3RhcnRpbmcgd2l0aCAidGVzdCIgdGhhdCB0YWtlIG5vIGFyZ3VtZW50cy4KICoKICogQHNlZSBUZXN0CiAqLwpwdWJsaWMgY2xhc3MgVGVzdFN1aXRlIGltcGxlbWVudHMgVGVzdCB7CgoJcHJpdmF0ZSBWZWN0b3IgZlRlc3RzPSBuZXcgVmVjdG9yKDEwKTsKCXByaXZhdGUgU3RyaW5nIGZOYW1lOwoKCS8qKgoJICogQ29uc3RydWN0cyBhbiBlbXB0eSBUZXN0U3VpdGUuCgkgKi8KCXB1YmxpYyBUZXN0U3VpdGUoKSB7Cgl9CgoJLyoqCgkgKiBDb25zdHJ1Y3RzIGEgVGVzdFN1aXRlIGZyb20gdGhlIGdpdmVuIGNsYXNzIHdpdGggdGhlIGdpdmVuIG5hbWUuCgkgKiBAc2VlIFRlc3RTdWl0ZSNUZXN0U3VpdGUoQ2xhc3MpCgkgKi8KCXB1YmxpYyBUZXN0U3VpdGUoQ2xhc3MgdGhlQ2xhc3MsIFN0cmluZyBuYW1lKSB7CgkJdGhpcyh0aGVDbGFzcyk7CgkJc2V0TmFtZShuYW1lKTsKCX0KCgkvKioKCSAqIENvbnN0cnVjdHMgYSBUZXN0U3VpdGUgZnJvbSB0aGUgZ2l2ZW4gY2xhc3MuIEFkZHMgYWxsIHRoZSBtZXRob2RzCgkgKiBzdGFydGluZyB3aXRoICJ0ZXN0IiBhcyB0ZXN0IGNhc2VzIHRvIHRoZSBzdWl0ZS4KCSAqIFBhcnRzIG9mIHRoaXMgbWV0aG9kIHdhcyB3cml0dGVuIGF0IDIzMzcgbWV0ZXJzIGluIHRoZSBI/GZmaWj8dHRlLAoJICogS2FudG9uIFVyaQoJICovCglwdWJsaWMgVGVzdFN1aXRlKGZpbmFsIENsYXNzIHRoZUNsYXNzKSB7CgkJZk5hbWU9IHRoZUNsYXNzLmdldE5hbWUoKTsKCQl0cnkgewoJCQlnZXRUZXN0Q29uc3RydWN0b3IodGhlQ2xhc3MpOyAvLyBBdm9pZCBnZW5lcmF0aW5nIG11bHRpcGxlIGVycm9yIG1lc3NhZ2VzCgkJfSBjYXRjaCAoTm9TdWNoTWV0aG9kRXhjZXB0aW9uIGUpIHsKCQkJYWRkVGVzdCh3YXJuaW5nKCJDbGFzcyAiK3RoZUNsYXNzLmdldE5hbWUoKSsiIGhhcyBubyBwdWJsaWMgY29uc3RydWN0b3IgVGVzdENhc2UoU3RyaW5nIG5hbWUpIG9yIFRlc3RDYXNlKCkiKSk7CgkJCXJldHVybjsKCQl9CgoJCWlmICghTW9kaWZpZXIuaXNQdWJsaWModGhlQ2xhc3MuZ2V0TW9kaWZpZXJzKCkpKSB7CgkJCWFkZFRlc3Qod2FybmluZygiQ2xhc3MgIit0aGVDbGFzcy5nZXROYW1lKCkrIiBpcyBub3QgcHVibGljIikpOwoJCQlyZXR1cm47CgkJfQoKCQlDbGFzcyBzdXBlckNsYXNzPSB0aGVDbGFzczsKCQlWZWN0b3IgbmFtZXM9IG5ldyBWZWN0b3IoKTsKCQl3aGlsZSAoVGVzdC5jbGFzcy5pc0Fzc2lnbmFibGVGcm9tKHN1cGVyQ2xhc3MpKSB7CgkJCU1ldGhvZFtdIG1ldGhvZHM9IHN1cGVyQ2xhc3MuZ2V0RGVjbGFyZWRNZXRob2RzKCk7CgkJCWZvciAoaW50IGk9IDA7IGkgPCBtZXRob2RzLmxlbmd0aDsgaSsrKSB7CgkJCQlhZGRUZXN0TWV0aG9kKG1ldGhvZHNbaV0sIG5hbWVzLCB0aGVDbGFzcyk7CgkJCX0KCQkJc3VwZXJDbGFzcz0gc3VwZXJDbGFzcy5nZXRTdXBlcmNsYXNzKCk7CgkJfQoJCWlmIChmVGVzdHMuc2l6ZSgpID09IDApCgkJCWFkZFRlc3Qod2FybmluZygiTm8gdGVzdHMgZm91bmQgaW4gIit0aGVDbGFzcy5nZXROYW1lKCkpKTsKCX0KCgkvKioKCSAqIENvbnN0cnVjdHMgYW4gZW1wdHkgVGVzdFN1aXRlLgoJICovCglwdWJsaWMgVGVzdFN1aXRlKFN0cmluZyBuYW1lKSB7CgkJc2V0TmFtZShuYW1lKTsKCX0KCgkvKioKCSAqIEFkZHMgYSB0ZXN0IHRvIHRoZSBzdWl0ZS4KCSAqLwoJcHVibGljIHZvaWQgYWRkVGVzdChUZXN0IHRlc3QpIHsKCQlmVGVzdHMuYWRkRWxlbWVudCh0ZXN0KTsKCX0KCgkvKioKCSAqIEFkZHMgdGhlIHRlc3RzIGZyb20gdGhlIGdpdmVuIGNsYXNzIHRvIHRoZSBzdWl0ZQoJICovCglwdWJsaWMgdm9pZCBhZGRUZXN0U3VpdGUoQ2xhc3MgdGVzdENsYXNzKSB7CgkJYWRkVGVzdChuZXcgVGVzdFN1aXRlKHRlc3RDbGFzcykpOwoJfQoKCXByaXZhdGUgdm9pZCBhZGRUZXN0TWV0aG9kKE1ldGhvZCBtLCBWZWN0b3IgbmFtZXMsIENsYXNzIHRoZUNsYXNzKSB7CgkJU3RyaW5nIG5hbWU9IG0uZ2V0TmFtZSgpOwoJCWlmIChuYW1lcy5jb250YWlucyhuYW1lKSkKCQkJcmV0dXJuOwoJCWlmICghIGlzUHVibGljVGVzdE1ldGhvZChtKSkgewoJCQlpZiAoaXNUZXN0TWV0aG9kKG0pKQoJCQkJYWRkVGVzdCh3YXJuaW5nKCJUZXN0IG1ldGhvZCBpc24ndCBwdWJsaWM6ICIrbS5nZXROYW1lKCkpKTsKCQkJcmV0dXJuOwoJCX0KCQluYW1lcy5hZGRFbGVtZW50KG5hbWUpOwoJCWFkZFRlc3QoY3JlYXRlVGVzdCh0aGVDbGFzcywgbmFtZSkpOwoJfQoKCS8qKgoJICogLi4uYXMgdGhlIG1vb24gc2V0cyBvdmVyIHRoZSBlYXJseSBtb3JuaW5nIE1lcmxpbiwgT3JlZ29uCgkgKiBtb3VudGFpbnMsIG91ciBpbnRyZXBpZCBhZHZlbnR1cmVycyB0eXBlLi4uCgkgKi8KCXN0YXRpYyBwdWJsaWMgVGVzdCBjcmVhdGVUZXN0KENsYXNzIHRoZUNsYXNzLCBTdHJpbmcgbmFtZSkgewoJCUNvbnN0cnVjdG9yIGNvbnN0cnVjdG9yOwoJCXRyeSB7CgkJCWNvbnN0cnVjdG9yPSBnZXRUZXN0Q29uc3RydWN0b3IodGhlQ2xhc3MpOwoJCX0gY2F0Y2ggKE5vU3VjaE1ldGhvZEV4Y2VwdGlvbiBlKSB7CgkJCXJldHVybiB3YXJuaW5nKCJDbGFzcyAiK3RoZUNsYXNzLmdldE5hbWUoKSsiIGhhcyBubyBwdWJsaWMgY29uc3RydWN0b3IgVGVzdENhc2UoU3RyaW5nIG5hbWUpIG9yIFRlc3RDYXNlKCkiKTsKCQl9CgkJT2JqZWN0IHRlc3Q7CgkJdHJ5IHsKCQkJaWYgKGNvbnN0cnVjdG9yLmdldFBhcmFtZXRlclR5cGVzKCkubGVuZ3RoID09IDApIHsKCQkJCXRlc3Q9IGNvbnN0cnVjdG9yLm5ld0luc3RhbmNlKG5ldyBPYmplY3RbMF0pOwoJCQkJaWYgKHRlc3QgaW5zdGFuY2VvZiBUZXN0Q2FzZSkKCQkJCQkoKFRlc3RDYXNlKSB0ZXN0KS5zZXROYW1lKG5hbWUpOwoJCQl9IGVsc2UgewoJCQkJdGVzdD0gY29uc3RydWN0b3IubmV3SW5zdGFuY2UobmV3IE9iamVjdFtde25hbWV9KTsKCQkJfQoJCX0gY2F0Y2ggKEluc3RhbnRpYXRpb25FeGNlcHRpb24gZSkgewoJCQlyZXR1cm4od2FybmluZygiQ2Fubm90IGluc3RhbnRpYXRlIHRlc3QgY2FzZTogIituYW1lKyIgKCIrZXhjZXB0aW9uVG9TdHJpbmcoZSkrIikiKSk7CgkJfSBjYXRjaCAoSW52b2NhdGlvblRhcmdldEV4Y2VwdGlvbiBlKSB7CgkJCXJldHVybih3YXJuaW5nKCJFeGNlcHRpb24gaW4gY29uc3RydWN0b3I6ICIrbmFtZSsiICgiK2V4Y2VwdGlvblRvU3RyaW5nKGUuZ2V0VGFyZ2V0RXhjZXB0aW9uKCkpKyIpIikpOwoJCX0gY2F0Y2ggKElsbGVnYWxBY2Nlc3NFeGNlcHRpb24gZSkgewoJCQlyZXR1cm4od2FybmluZygiQ2Fubm90IGFjY2VzcyB0ZXN0IGNhc2U6ICIrbmFtZSsiICgiK2V4Y2VwdGlvblRvU3RyaW5nKGUpKyIpIikpOwoJCX0KCQlyZXR1cm4gKFRlc3QpIHRlc3Q7Cgl9CgoJLyoqCgkgKiBDb252ZXJ0cyB0aGUgc3RhY2sgdHJhY2UgaW50byBhIHN0cmluZwoJICovCglwcml2YXRlIHN0YXRpYyBTdHJpbmcgZXhjZXB0aW9uVG9TdHJpbmcoVGhyb3dhYmxlIHQpIHsKCQlTdHJpbmdXcml0ZXIgc3RyaW5nV3JpdGVyPSBuZXcgU3RyaW5nV3JpdGVyKCk7CgkJUHJpbnRXcml0ZXIgd3JpdGVyPSBuZXcgUHJpbnRXcml0ZXIoc3RyaW5nV3JpdGVyKTsKCQl0LnByaW50U3RhY2tUcmFjZSh3cml0ZXIpOwoJCXJldHVybiBzdHJpbmdXcml0ZXIudG9TdHJpbmcoKTsKCgl9CgoJLyoqCgkgKiBDb3VudHMgdGhlIG51bWJlciBvZiB0ZXN0IGNhc2VzIHRoYXQgd2lsbCBiZSBydW4gYnkgdGhpcyB0ZXN0LgoJICovCglwdWJsaWMgaW50IGNvdW50VGVzdENhc2VzKCkgewoJCWludCBjb3VudD0gMDsKCQlmb3IgKEVudW1lcmF0aW9uIGU9IHRlc3RzKCk7IGUuaGFzTW9yZUVsZW1lbnRzKCk7ICkgewoJCQlUZXN0IHRlc3Q9IChUZXN0KWUubmV4dEVsZW1lbnQoKTsKCQkJY291bnQ9IGNvdW50ICsgdGVzdC5jb3VudFRlc3RDYXNlcygpOwoJCX0KCQlyZXR1cm4gY291bnQ7Cgl9CgoJLyoqCgkgKiBHZXRzIGEgY29uc3RydWN0b3Igd2hpY2ggdGFrZXMgYSBzaW5nbGUgU3RyaW5nIGFzCgkgKiBpdHMgYXJndW1lbnQgb3IgYSBubyBhcmcgY29uc3RydWN0b3IuCgkgKi8KCXB1YmxpYyBzdGF0aWMgQ29uc3RydWN0b3IgZ2V0VGVzdENvbnN0cnVjdG9yKENsYXNzIHRoZUNsYXNzKSB0aHJvd3MgTm9TdWNoTWV0aG9kRXhjZXB0aW9uIHsKCQlDbGFzc1tdIGFyZ3M9IHsgU3RyaW5nLmNsYXNzIH07CgkJdHJ5IHsKCQkJcmV0dXJuIHRoZUNsYXNzLmdldENvbnN0cnVjdG9yKGFyZ3MpOwkKCQl9IGNhdGNoIChOb1N1Y2hNZXRob2RFeGNlcHRpb24gZSkgewoJCQkvLyBmYWxsIHRocm91Z2gKCQl9CgkJcmV0dXJuIHRoZUNsYXNzLmdldENvbnN0cnVjdG9yKG5ldyBDbGFzc1swXSk7Cgl9CgoJcHJpdmF0ZSBib29sZWFuIGlzUHVibGljVGVzdE1ldGhvZChNZXRob2QgbSkgewoJCXJldHVybiBpc1Rlc3RNZXRob2QobSkgJiYgTW9kaWZpZXIuaXNQdWJsaWMobS5nZXRNb2RpZmllcnMoKSk7Cgl9CgoJcHJpdmF0ZSBib29sZWFuIGlzVGVzdE1ldGhvZChNZXRob2QgbSkgewoJCVN0cmluZyBuYW1lPSBtLmdldE5hbWUoKTsKCQlDbGFzc1tdIHBhcmFtZXRlcnM9IG0uZ2V0UGFyYW1ldGVyVHlwZXMoKTsKCQlDbGFzcyByZXR1cm5UeXBlPSBtLmdldFJldHVyblR5cGUoKTsKCQlyZXR1cm4gcGFyYW1ldGVycy5sZW5ndGggPT0gMCAmJiBuYW1lLnN0YXJ0c1dpdGgoInRlc3QiKSAmJiByZXR1cm5UeXBlLmVxdWFscyhWb2lkLlRZUEUpOwoJfQoKCS8qKgoJICogUnVucyB0aGUgdGVzdHMgYW5kIGNvbGxlY3RzIHRoZWlyIHJlc3VsdCBpbiBhIFRlc3RSZXN1bHQuCgkgKi8KCXB1YmxpYyB2b2lkIHJ1bihUZXN0UmVzdWx0IHJlc3VsdCkgewoJCWZvciAoRW51bWVyYXRpb24gZT0gdGVzdHMoKTsgZS5oYXNNb3JlRWxlbWVudHMoKTsgKSB7CgkJCWlmIChyZXN1bHQuc2hvdWxkU3RvcCgpICkKCQkJCWJyZWFrOwoJCQlUZXN0IHRlc3Q9IChUZXN0KWUubmV4dEVsZW1lbnQoKTsKCQkJcnVuVGVzdCh0ZXN0LCByZXN1bHQpOwoJCX0KCX0KCglwdWJsaWMgdm9pZCBydW5UZXN0KFRlc3QgdGVzdCwgVGVzdFJlc3VsdCByZXN1bHQpIHsKCQl0ZXN0LnJ1bihyZXN1bHQpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgdGVzdCBhdCB0aGUgZ2l2ZW4gaW5kZXgKCSAqLwoJcHVibGljIFRlc3QgdGVzdEF0KGludCBpbmRleCkgewoJCXJldHVybiAoVGVzdClmVGVzdHMuZWxlbWVudEF0KGluZGV4KTsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIG51bWJlciBvZiB0ZXN0cyBpbiB0aGlzIHN1aXRlCgkgKi8KCXB1YmxpYyBpbnQgdGVzdENvdW50KCkgewoJCXJldHVybiBmVGVzdHMuc2l6ZSgpOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgdGVzdHMgYXMgYW4gZW51bWVyYXRpb24KCSAqLwoJcHVibGljIEVudW1lcmF0aW9uIHRlc3RzKCkgewoJCXJldHVybiBmVGVzdHMuZWxlbWVudHMoKTsKCX0KCgkvKioKCSAqLwoJcHVibGljIFN0cmluZyB0b1N0cmluZygpIHsKCQlpZiAoZ2V0TmFtZSgpICE9IG51bGwpCgkJCXJldHVybiBnZXROYW1lKCk7CgkJcmV0dXJuIHN1cGVyLnRvU3RyaW5nKCk7Cgl9CgoJLyoqCgkgKiBTZXRzIHRoZSBuYW1lIG9mIHRoZSBzdWl0ZS4KCSAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIHRvIHNldAoJICovCglwdWJsaWMgdm9pZCBzZXROYW1lKFN0cmluZyBuYW1lKSB7CgkJZk5hbWU9IG5hbWU7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSBzdWl0ZS4gTm90IGFsbAoJICogdGVzdCBzdWl0ZXMgaGF2ZSBhIG5hbWUgYW5kIHRoaXMgbWV0aG9kCgkgKiBjYW4gcmV0dXJuIG51bGwuCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0TmFtZSgpIHsKCQlyZXR1cm4gZk5hbWU7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIGEgdGVzdCB3aGljaCB3aWxsIGZhaWwgYW5kIGxvZyBhIHdhcm5pbmcgbWVzc2FnZS4KCSAqLwoJcHJpdmF0ZSBzdGF0aWMgVGVzdCB3YXJuaW5nKGZpbmFsIFN0cmluZyBtZXNzYWdlKSB7CgkJcmV0dXJuIG5ldyBUZXN0Q2FzZSgid2FybmluZyIpIHsKCQkJcHJvdGVjdGVkIHZvaWQgcnVuVGVzdCgpIHsKCQkJCWZhaWwobWVzc2FnZSk7CgkJCX0KCQl9OwoJfQp9