diff --git a/Makefile b/Makefile index b8d7733..0fca51c 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ -OLD_SHA:=$(shell shasum -a 256 main-packr.go | cut -d' ' -f1) -NEW_SHA= $(shell shasum -a 256 main-packr.go | cut -d' ' -f1) +OLD_SHA:=$(shell shasum -a 256 a_main-packr.go | cut -d' ' -f1) +NEW_SHA= $(shell shasum -a 256 a_main-packr.go | cut -d' ' -f1) all: test install post test: - go test -v ./... + go test -v -count 1 ./... go build docker-compose --no-ansi -f docker-compose.yml up -d --force-recreate sleep 5 @@ -12,7 +12,7 @@ test: rm -rf modelgen rm -rf ./generated_models test-ci: - go test -v ./... + go test -v -count 1 ./... go build docker-compose --no-ansi -f docker-compose.yml up -d --force-recreate sleep 30 # annoying, but for ci. @@ -26,6 +26,6 @@ install: packr && go install post: @if [ "$(NEW_SHA)" != "$(OLD_SHA)" ]; then\ - echo "sha comparison failed on main-packr.go";\ + echo "sha comparison failed on a_main-packr.go";\ exit 1;\ fi diff --git a/main-packr.go b/a_main-packr.go similarity index 80% rename from main-packr.go rename to a_main-packr.go index 226bba3..6eaacfc 100644 --- a/main-packr.go +++ b/a_main-packr.go @@ -1,17 +1,15 @@ +// Code generated by github.com/gobuffalo/packr. DO NOT EDIT. + package main import "github.com/gobuffalo/packr" -// !!! GENERATED FILE !!! -// Do NOT hand edit this file!! -// It is recommended that you DO NOT check into this file into SCM. -// We STRONGLY recommend you delete this file after you have built your -// Go binary. You can use the "packr clean" command to clean up this, +// You can use the "packr clean" command to clean up this, // and any other packr generated files. func init() { - packr.PackJSONBytes("./tmpl", "model.html", "\"e3tkZWZpbmUgIm1vZGVsIn19CnBhY2thZ2Uge3sgLlBhY2thZ2VOYW1lIH19CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCBDb2RlIGdlbmVyYXRlZCBieSBtb2RlbGdlbiB8CnwgICAgICAgIERPIE5PVCBFRElULiAgICAgICAgfAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KCi8vIElmIHlvdSB3YW50IHRvIGV4dGVuZCBiZWhhdmlvdXI6Ci8vIFBsZWFzZSBjcmVhdGUgYSBjdXN0b20gZmlsZSBpbiB0aGlzIGRpcmVjdG9yeQovLyBhbmQgY3JlYXRlIHRoZSBtZXRob2RzIHRoZXJlIHRvIGF2b2lkIG92ZXJ3cml0aW5nIHlvdXIgY29kZSB3aXRoIHRoZSBnZW5lcmF0ZWQgb25lLgoKaW1wb3J0ICgKImZtdCIKICAgIHt7IHJhbmdlICRrLCAkdjo9IC5Nb2RlbC5JbXBvcnRzIH19CiAgICAie3ska319IgogICAge3stIGVuZCB9fQopCgovLyB7ey5Nb2RlbC5OYW1lfX0gcmVwcmVzZW50cyBhIHJvdyBpbiB0aGUge3suTW9kZWwuVGFibGVOYW1lfX0gdGFibGUKdHlwZSB7ey5Nb2RlbC5OYW1lfX0gc3RydWN0IHsKICAgIHt7IHJhbmdlICRrLCAkdjo9IC5Nb2RlbC5GaWVsZHMgfX0KICAgICAgICB7eyAkdi5OYW1lIH19IHt7ICR2LlR5cGUgfX0gYGpzb246Int7JHYuQ29sdW1uTmFtZX19ImAKICAgIHt7LSBlbmQgfX0Kb2Zmc2V0IGludApsaW1pdCBpbnQKfQoKLy8gSW5zZXJ0IGEgbmV3IHt7Lk1vZGVsLk5hbWV9fSByb3cgaW4gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlCmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgSW5zZXJ0KHF1IFF1ZXJ5ZXIpIChsYXN0SW5zZXJ0SUQgaW50NjQsIGVyciBlcnJvcikgewogICAgY29uc3Qgc3RtdCA9ICJJTlNFUlQgSU5UTyB7ey5Nb2RlbC5UYWJsZU5hbWV9fSAoe3suTW9kZWwuRmllbGRzIHwgaW5zZXJ0X2ZpZWxkc319KSBWQUxVRVMgKHt7Lk1vZGVsLkZpZWxkcyB8IGluc2VydF92YWx1ZXN9fSkiCiAgICByZXMsIGVyciA6PSBxdS5FeGVjKHN0bXQsIHt7IC4gfCBpbnNlcnRfYXJncyB9fSkKICAgIGlmIGVyciAhPSBuaWwgewogICAgICAgIHJldHVybiAwLCBlcnIKICAgIH0KICAgIHJldHVybiByZXMuTGFzdEluc2VydElkKCkKfQoKLy8gVXBkYXRlIGFuIGV4aXN0aW5nIHt7Lk1vZGVsLk5hbWV9fSByb3cgaW4gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlLgpmdW5jICh7ey5SZWNlaXZlcn19ICp7ey5Nb2RlbC5OYW1lfX0pIFVwZGF0ZShxdSBRdWVyeWVyLCBpZCBpbnQ2NCkgKGludDY0LCBlcnJvcikgewogICAgY29uc3Qgc3RtdCA9ICJVUERBVEUge3suTW9kZWwuVGFibGVOYW1lfX0gU0VUIHt7IC4gfCB1cGRhdGVfdmFsdWVzIH19IFdIRVJFIGlkID0gPyIKICAgIHJlc3VsdCwgZXJyIDo9IHF1LkV4ZWMoc3RtdCwge3sgLiB8IHVwZGF0ZV9hcmdzIH19ICwgaWQpCiAgICBpZiBlcnIgIT0gbmlsIHsKICAgICAgICByZXR1cm4gMCwgZXJyCiAgICB9CiAgICByZXR1cm4gcmVzdWx0LlJvd3NBZmZlY3RlZCgpCn0KCi8vIFVwc2VydCBpbnNlcnRzIGEgbmV3IHt7Lk1vZGVsLk5hbWV9fSByb3cgaW4gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlCi8vIGlmIHRoZSB1bmlxdWUgY29uc3RyYWludHMgYXJlIG5vdCBmb3VuZCwgb3RoZXJ3aXNlIGl0IHVwZGF0ZXMgaXQuCmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgVXBzZXJ0KHF1IFF1ZXJ5ZXIpIChsYXN0SW5zZXJ0SUQgaW50NjQsIGVyciBlcnJvcikgewogICAgY29uc3Qgc3RtdCA9ICJJTlNFUlQgSU5UTyB7ey5Nb2RlbC5UYWJsZU5hbWV9fSAoe3suTW9kZWwuRmllbGRzIHwgdXBzZXJ0X2ZpZWxkc319KSBWQUxVRVMgKHt7Lk1vZGVsLkZpZWxkcyB8IHVwc2VydF92YWx1ZXN9fSkgT04gRFVQTElDQVRFIEtFWSBVUERBVEUge3sgLiB8IHVwc2VydF9vbl9kdXBsaWNhdGUgfX0iCiAgICByZXMsIGVyciA6PSBxdS5FeGVjKHN0bXQsIHt7IC4gfCB1cHNlcnRfYXJncyB9fSkKICAgIGlmIGVyciAhPSBuaWwgewogICAgICAgIHJldHVybiAwLCBlcnIKICAgIH0KICAgIHJldHVybiByZXMuTGFzdEluc2VydElkKCkKfQoKLy8gRmluZCBhbiBleGlzdGluZyB7ey5Nb2RlbC5OYW1lfX0gcm93IGluIHRoZSB7ey5Nb2RlbC5UYWJsZU5hbWV9fSB0YWJsZQpmdW5jICh7ey5SZWNlaXZlcn19ICp7ey5Nb2RlbC5OYW1lfX0pIEZpbmQocXUgUXVlcnllciwgaWQgaW50NjQpIGVycm9yIHsKICAgIGNvbnN0IHN0bXQgPSAiU0VMRUNUICogRlJPTSB7ey5Nb2RlbC5UYWJsZU5hbWV9fSBXSEVSRSBpZCA9ID8iCiAgICByb3cgOj0gcXUuUXVlcnlSb3coc3RtdCwgaWQpCiAgICByZXR1cm4gcm93LlNjYW4oe3sgLiB8IHNjYW5fZmllbGRzfX0pCn0KCi8vIExvYWQgYWxsLCBvciBhIHN1YnNldCBvZiB7ey5Nb2RlbC5OYW1lfX0gcm93cyBmcm9tIHRoZSB7ey5Nb2RlbC5UYWJsZU5hbWV9fSB0YWJsZQpmdW5jICh7ey5SZWNlaXZlcn19ICp7ey5Nb2RlbC5OYW1lfX0pIExvYWQocXUgUXVlcnllcikgKHNldCBbXXt7Lk1vZGVsLk5hbWV9fSwgZXJyIGVycm9yKSB7CiAgICBzdG10IDo9ICJTRUxFQ1QgKiBGUk9NIHt7Lk1vZGVsLlRhYmxlTmFtZX19IgoKICAgIGlmIHt7LlJlY2VpdmVyfX0ubGltaXQgPT0gMCAmJiB7ey5SZWNlaXZlcn19Lm9mZnNldCA+IDAgewogICAgICAgIHJldHVybiBzZXQsIGZtdC5FcnJvcmYoImNhbm5vdCBxdWVyeSB3aXRoIG9mZnNldCBidXQgbm8gbGltaXQiKQogICAgfQoKICAgIGlmIHt7LlJlY2VpdmVyfX0ubGltaXQgPiAwIHsKICAgICAgICBzdG10ICs9IGZtdC5TcHJpbnRmKCIgTElNSVQgJWQiLCB7ey5SZWNlaXZlcn19LmxpbWl0KQogICAgfQogICAgaWYge3suUmVjZWl2ZXJ9fS5vZmZzZXQgPiAwIHsKICAgICAgICBzdG10ICs9IGZtdC5TcHJpbnRmKCIgT0ZGU0VUICVkIiwge3suUmVjZWl2ZXJ9fS5vZmZzZXQpCiAgICB9CiAgICBkZWZlciBmdW5jKCkgewogICAgICAgIHt7LlJlY2VpdmVyfX0ubGltaXQgPSAwCiAgICAgICAge3suUmVjZWl2ZXJ9fS5vZmZzZXQgPSAwCiAgICB9KCkKICAgIHJvd3MsIGVyciA6PSBxdS5RdWVyeShzdG10KQogICAgaWYgZXJyICE9IG5pbCB7CiAgICAgICAgcmV0dXJuCiAgICB9CiAgICBkZWZlciByb3dzLkNsb3NlKCkKICAgICAgICBmb3Igcm93cy5OZXh0KCkgewogICAgICAgICAgICB2YXIge3suUmVjZWl2ZXJ9fSB7ey5Nb2RlbC5OYW1lfX0KICAgICAgICAgICAgaWYgZXJyID0gcm93cy5TY2FuKHt7LiB8IHNjYW5fZmllbGRzfX0pOyBlcnIgIT0gbmlsIHsKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgfQogICAgICAgIHNldCA9IGFwcGVuZChzZXQsIHt7LlJlY2VpdmVyfX0pCiAgICB9CgogICAgcmV0dXJuCn0KCi8vIERlbGV0ZSBhbiBleGlzdGluZyB7ey5Nb2RlbC5OYW1lfX0gcm93IGZyb20gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlCmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgRGVsZXRlKHF1IFF1ZXJ5ZXIsIGlkIGludDY0KSAocm93c0FmZmVjdGVkIGludDY0LCBlcnIgZXJyb3IpIHsKICAgIGNvbnN0IHN0bXQgPSAiREVMRVRFIEZST00ge3suTW9kZWwuVGFibGVOYW1lfX0gV0hFUkUgaWQgPSA/IgogICAgcmVzdWx0LCBlcnIgOj0gcXUuRXhlYyhzdG10LCBpZCkKCWlmIGVyciAhPSBuaWwgewoJCXJldHVybgoJfQoKCXJldHVybiByZXN1bHQuUm93c0FmZmVjdGVkKCkKfQoKLy8gQ291bnQgdGhlIG51bWJlciBvZiByb3dzIGZyb20gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlCmZ1bmMoe3suUmVjZWl2ZXJ9fSAqe3suTW9kZWwuTmFtZX19KSBDb3VudChxdSBRdWVyeWVyKSAoY291bnQgaW50NjQsIGVyciBlcnJvcikgewogICAgY29uc3Qgc3RtdCA9ICJTRUxFQ1QgQ09VTlQoKikgRlJPTSB7ey5Nb2RlbC5UYWJsZU5hbWV9fSIKICAgIHJvdyA6PSBxdS5RdWVyeVJvdyhzdG10KQogICAgaWYgZXJyID0gcm93LlNjYW4oJmNvdW50KTsgZXJyICE9IG5pbCB7CiAgICAgICAgcmV0dXJuCiAgICB9CiAgICByZXR1cm4KfQoKLy8gRXhpc3RzIGNoZWNrcyBmb3IgdGhlIGl0ZW1zIGV4aXN0ZW5jZSBpbiB0aGUgZGF0YWJhc2UsIGJhc2VkIG9uIGl0J3MgaWQuCi8vIEFuIGVycm9yIHdpbGwgb25seSBiZSByZXR1cm5lZCBpZiBhIFNRTCByZWxhdGVkIGZhaWx1cmUgaGFwcGVucy4KLy8gSW4gYWxsIG90aGVyIGNhc2VzLCBhIGJvb2wgYW5kIG5pbCB3aWxsIHJldHVybi4KZnVuYyh7ey5SZWNlaXZlcn19ICp7ey5Nb2RlbC5OYW1lfX0pIEV4aXN0cyhxdSBRdWVyeWVyLCBpZCBpbnQ2NCkgKGV4aXN0cyBib29sLCBlcnIgZXJyb3IpIHsKICAgIGNvbnN0IHN0bXQgPSAiU0VMRUNUIEVYSVNUUyhTRUxFQ1QgMSBGUk9NIHt7Lk1vZGVsLlRhYmxlTmFtZX19IFdIRVJFIGlkID0gPyBMSU1JVCAxKSBBUyBgZXhpc3RzYCIKICAgIHZhciBjb3VudCBpbnQKICAgIHJvdyA6PSBxdS5RdWVyeVJvdyhzdG10LCBpZCkKICAgIGlmIGVyciA9IHJvdy5TY2FuKCZjb3VudCk7IGVyciAhPSBuaWwgewogICAgICAgIHJldHVybgogICAgfQogICAgcmV0dXJuIGNvdW50ID4gMCwgbmlsCn0KCi8vIFRhYmxlTmFtZSByZXR1cm5zIHRoZSB0YWJsZSBuYW1lCmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgVGFibGVOYW1lKCkgc3RyaW5nIHsKcmV0dXJuICJ7ey5Nb2RlbC5UYWJsZU5hbWV9fSIKfQoKLy8gU2V0TGltaXQgc2V0cyB0aGUgcXVlcnkgbGltaXQKZnVuYyAoe3suUmVjZWl2ZXJ9fSAqe3suTW9kZWwuTmFtZX19KSBTZXRMaW1pdChsaW1pdCBpbnQpICp7ey5Nb2RlbC5OYW1lfX0gewp7ey5SZWNlaXZlcn19LmxpbWl0ID0gbGltaXQKcmV0dXJuIHt7LlJlY2VpdmVyfX0KfQoKLy8gU2V0T2Zmc2V0IHNldHMgdGhlIHF1ZXJ5IG9mZnNldApmdW5jICh7ey5SZWNlaXZlcn19ICp7ey5Nb2RlbC5OYW1lfX0pIFNldE9mZnNldChvZmZzZXQgaW50KSAqe3suTW9kZWwuTmFtZX19IHsKe3suUmVjZWl2ZXJ9fS5vZmZzZXQgPSBvZmZzZXQKcmV0dXJuIHt7LlJlY2VpdmVyfX0KfQp7e2VuZH19Cgo=\"") - packr.PackJSONBytes("./tmpl", "tmpl.go", "\"cGFja2FnZSB0bXBsCgppbXBvcnQgKAoJImZtdCIKCSJodG1sL3RlbXBsYXRlIgoJInN0cmluZ3MiCikKCnZhciBGdW5jTWFwID0gdGVtcGxhdGUuRnVuY01hcHsKCSJpbnNlcnRfZmllbGRzIjogR2V0SW5zZXJ0RmllbGRzLAoJImluc2VydF92YWx1ZXMiOiBHZXRJbnNlcnRWYWx1ZXMsCgkiaW5zZXJ0X2FyZ3MiOiAgIEdldEluc2VydEFyZ3MsCgkic2Nhbl9maWVsZHMiOiAgIEdldFNjYW5GaWVsZHMsCgkidXBkYXRlX2FyZ3MiOiAgIEdldFVwZGF0ZUFyZ3MsCgkidXBkYXRlX3ZhbHVlcyI6IEdldFVwZGF0ZVZhbHVlcywKCSJ1cHNlcnRfZmllbGRzIjogR2V0VXBzZXJ0RmllbGRzLAoJInVwc2VydF92YWx1ZXMiOiBHZXRVcHNlcnRWYWx1ZXMsCgkidXBzZXJ0X29uX2R1cGxpY2F0ZSI6IEdldFVwc2VydE9uRHVwbGljYXRlLAoJInVwc2VydF9hcmdzIjogR2V0VXBzZXJ0QXJncywKfQoKZnVuYyBHZXRJbnNlcnRGaWVsZHMoZmllbGRzIFtdVG1wbEZpZWxkKSBzdHJpbmcgewoJdmFyIHBhcnRzIFtdc3RyaW5nCglmb3IgXywgZmwgOj0gcmFuZ2UgZmllbGRzIHsKCQlpZiBmbC5Db2x1bW5OYW1lID09ICJpZCIgewoJCQljb250aW51ZQoJCX0KCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgImAiK2ZsLkNvbHVtbk5hbWUrImAiKQoJfQoJcmV0dXJuIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKfQoKZnVuYyBHZXRJbnNlcnRWYWx1ZXMoZmllbGRzIFtdVG1wbEZpZWxkKSBzdHJpbmcgewoJdmFyIHBhcnRzIFtdc3RyaW5nCglmb3IgXywgZmwgOj0gcmFuZ2UgZmllbGRzIHsKCQlzd2l0Y2ggZmwuQ29sdW1uTmFtZSB7CgkJY2FzZSAiaWQiOgoJCQljb250aW51ZQoJCWNhc2UgImNyZWF0ZWRfYXQiOgoJCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgIk5PVygpIikKCQkJY29udGludWUKCQlkZWZhdWx0OgoJCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgIj8iKQoJCX0KCX0KCXJldHVybiBzdHJpbmdzLkpvaW4ocGFydHMsICIsICIpCn0KCmZ1bmMgR2V0SW5zZXJ0QXJncyhtIFN0cnVjdFRtcGxEYXRhKSBzdHJpbmcgewoJdmFyIHBhcnRzIFtdc3RyaW5nCglmb3IgXywgZmwgOj0gcmFuZ2UgbS5Nb2RlbC5GaWVsZHMgewoJCXN3aXRjaCBmbC5OYW1lIHsKCQljYXNlICJJRCIsICJDcmVhdGVkQXQiOgoJCQljb250aW51ZQoJCX0KCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgZm10LlNwcmludGYoIiVzLiVzIiwgbS5SZWNlaXZlciwgZmwuTmFtZSkpCgl9CglyZXR1cm4gc3RyaW5ncy5Kb2luKHBhcnRzLCAiLCAiKQp9CgpmdW5jIEdldFNjYW5GaWVsZHMobSBTdHJ1Y3RUbXBsRGF0YSkgdGVtcGxhdGUuSFRNTCB7Cgl2YXIgcGFydHMgW11zdHJpbmcKCWZvciBfLCBmbCA6PSByYW5nZSBtLk1vZGVsLkZpZWxkcyB7CgkJcGFydHMgPSBhcHBlbmQocGFydHMsIGZtdC5TcHJpbnRmKCImJXMuJXMiLCBtLlJlY2VpdmVyLCBmbC5OYW1lKSkKCX0KCXJldHVybiB0ZW1wbGF0ZS5IVE1MKHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikpCn0KCmZ1bmMgR2V0VXBkYXRlQXJncyhtIFN0cnVjdFRtcGxEYXRhKSB0ZW1wbGF0ZS5IVE1MIHsKCXZhciBwYXJ0cyBbXXN0cmluZwoJZm9yIF8sIGZsIDo9IHJhbmdlIG0uTW9kZWwuRmllbGRzIHsKCQlzd2l0Y2ggZmwuTmFtZSB7CgkJY2FzZSAiSUQiLCAiQ3JlYXRlZEF0IiwgIlVwZGF0ZWRBdCI6CgkJCWNvbnRpbnVlCgkJfQoJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiJXMuJXMiLCBtLlJlY2VpdmVyLCBmbC5OYW1lKSkKCX0KCXJldHVybiB0ZW1wbGF0ZS5IVE1MKHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikpCn0KCmZ1bmMgR2V0VXBkYXRlVmFsdWVzKG0gU3RydWN0VG1wbERhdGEpIHN0cmluZyB7Cgl2YXIgcGFydHMgW11zdHJpbmcKCWZvciBfLCBmbCA6PSByYW5nZSBtLk1vZGVsLkZpZWxkcyB7CgkJc3dpdGNoIGZsLk5hbWUgewoJCWNhc2UgIklEIiwgIkNyZWF0ZWRBdCI6CgkJCWNvbnRpbnVlCgkJY2FzZSAiVXBkYXRlZEF0IjoKCQkJcGFydHMgPSBhcHBlbmQocGFydHMsIGZtdC5TcHJpbnRmKCJgJXNgPVVUQ19USU1FU1RBTVAoKSIsIGZsLkNvbHVtbk5hbWUpKQoJCWRlZmF1bHQ6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiYCVzYD0/IiwgZmwuQ29sdW1uTmFtZSkpCgkJfQoJfQoJcmV0dXJuIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKfQoKZnVuYyBHZXRVcHNlcnRGaWVsZHMoZmllbGRzIFtdVG1wbEZpZWxkKSBzdHJpbmcgewoJdmFyIHBhcnRzIFtdc3RyaW5nCglmb3IgXywgZmwgOj0gcmFuZ2UgZmllbGRzIHsKCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgImAiK2ZsLkNvbHVtbk5hbWUrImAiKQoJfQoJcmV0dXJuIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKfQoKZnVuYyBHZXRVcHNlcnRWYWx1ZXMoZmllbGRzIFtdVG1wbEZpZWxkKSBzdHJpbmcgewoJdmFyIHBhcnRzIFtdc3RyaW5nCglmb3IgXywgZmwgOj0gcmFuZ2UgZmllbGRzIHsKCQlzd2l0Y2ggZmwuQ29sdW1uTmFtZSB7CgkJY2FzZSAiY3JlYXRlZF9hdCI6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCAiTk9XKCkiKQoJCQljb250aW51ZQoJCWRlZmF1bHQ6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCAiPyIpCgkJfQoJfQoJcmV0dXJuIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKfQoKZnVuYyBHZXRVcHNlcnRPbkR1cGxpY2F0ZShtIFN0cnVjdFRtcGxEYXRhKSBzdHJpbmcgewoJdmFyIHBhcnRzIFtdc3RyaW5nCglmb3IgXywgZmwgOj0gcmFuZ2UgbS5Nb2RlbC5GaWVsZHMgewoJCXN3aXRjaCBmbC5OYW1lIHsKCQljYXNlICJDcmVhdGVkQXQiOgoJCQljb250aW51ZQoJCWNhc2UgIklEIjoKCQkJcGFydHMgPSBhcHBlbmQocGFydHMsIGZtdC5TcHJpbnRmKCJgJXNgPUxBU1RfSU5TRVJUX0lEKGAlc2ApIiwgZmwuQ29sdW1uTmFtZSwgZmwuQ29sdW1uTmFtZSkpCgkJY2FzZSAiVXBkYXRlZEF0IjoKCQkJcGFydHMgPSBhcHBlbmQocGFydHMsIGZtdC5TcHJpbnRmKCJgJXNgPVVUQ19USU1FU1RBTVAoKSIsIGZsLkNvbHVtbk5hbWUpKQoJCWRlZmF1bHQ6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiYCVzYD1WQUxVRVMoYCVzYCkiLCBmbC5Db2x1bW5OYW1lLCBmbC5Db2x1bW5OYW1lKSkKCQl9Cgl9CglyZXR1cm4gc3RyaW5ncy5Kb2luKHBhcnRzLCAiLCAiKQp9CgpmdW5jIEdldFVwc2VydEFyZ3MobSBTdHJ1Y3RUbXBsRGF0YSkgc3RyaW5nIHsKCXZhciBwYXJ0cyBbXXN0cmluZwoJZm9yIF8sIGZsIDo9IHJhbmdlIG0uTW9kZWwuRmllbGRzIHsKCQlzd2l0Y2ggZmwuTmFtZSB7CgkJY2FzZSAiQ3JlYXRlZEF0IjoKCQkJY29udGludWUKCQl9CgkJcGFydHMgPSBhcHBlbmQocGFydHMsIGZtdC5TcHJpbnRmKCIlcy4lcyIsIG0uUmVjZWl2ZXIsIGZsLk5hbWUpKQoJfQoJcmV0dXJuIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKfQ==\"") + packr.PackJSONBytes("./tmpl", "model.html", "\"e3tkZWZpbmUgIm1vZGVsIn19CnBhY2thZ2Uge3sgLlBhY2thZ2VOYW1lIH19CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCBDb2RlIGdlbmVyYXRlZCBieSBtb2RlbGdlbiB8CnwgICAgICAgIERPIE5PVCBFRElULiAgICAgICAgfAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KCi8vIElmIHlvdSB3YW50IHRvIGV4dGVuZCBiZWhhdmlvdXI6Ci8vIFBsZWFzZSBjcmVhdGUgYSBjdXN0b20gZmlsZSBpbiB0aGlzIGRpcmVjdG9yeQovLyBhbmQgY3JlYXRlIHRoZSBtZXRob2RzIHRoZXJlIHRvIGF2b2lkIG92ZXJ3cml0aW5nIHlvdXIgY29kZSB3aXRoIHRoZSBnZW5lcmF0ZWQgb25lLgoKaW1wb3J0ICgKImZtdCIKICAgIHt7IHJhbmdlICRrLCAkdjo9IC5Nb2RlbC5JbXBvcnRzIH19CiAgICAie3ska319IgogICAge3stIGVuZCB9fQopCgovLyB7ey5Nb2RlbC5OYW1lfX0gcmVwcmVzZW50cyBhIHJvdyBpbiB0aGUge3suTW9kZWwuVGFibGVOYW1lfX0gdGFibGUKdHlwZSB7ey5Nb2RlbC5OYW1lfX0gc3RydWN0IHsKICAgIHt7IHJhbmdlICRrLCAkdjo9IC5Nb2RlbC5GaWVsZHMgfX0KICAgICAgICB7eyAkdi5OYW1lIH19IHt7ICR2LlR5cGUgfX0gYGpzb246Int7JHYuQ29sdW1uTmFtZX19ImAKICAgIHt7LSBlbmQgfX0Kb2Zmc2V0IGludApsaW1pdCBpbnQKfQoKLy8gSW5zZXJ0IGEgbmV3IHt7Lk1vZGVsLk5hbWV9fSByb3cgaW4gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlCmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgSW5zZXJ0KHF1IFF1ZXJ5ZXIpIChsYXN0SW5zZXJ0SUQgaW50NjQsIGVyciBlcnJvcikgewogICAgY29uc3Qgc3RtdCA9ICJJTlNFUlQgSU5UTyB7ey5Nb2RlbC5UYWJsZU5hbWV9fSAoe3suTW9kZWwuRmllbGRzIHwgaW5zZXJ0X2ZpZWxkc319KSBWQUxVRVMgKHt7Lk1vZGVsLkZpZWxkcyB8IGluc2VydF92YWx1ZXN9fSkiCiAgICByZXMsIGVyciA6PSBxdS5FeGVjKHN0bXR7eyAuIHwgaW5zZXJ0X2FyZ3MgfX0pCiAgICBpZiBlcnIgIT0gbmlsIHsKICAgICAgICByZXR1cm4gMCwgZXJyCiAgICB9CiAgICByZXR1cm4gcmVzLkxhc3RJbnNlcnRJZCgpCn0KCi8vIFVwZGF0ZSBhbiBleGlzdGluZyB7ey5Nb2RlbC5OYW1lfX0gcm93IGluIHRoZSB7ey5Nb2RlbC5UYWJsZU5hbWV9fSB0YWJsZS4KZnVuYyAoe3suUmVjZWl2ZXJ9fSAqe3suTW9kZWwuTmFtZX19KSBVcGRhdGUocXUgUXVlcnllciwgaWQgaW50NjQpIChpbnQ2NCwgZXJyb3IpIHsKICAgIGNvbnN0IHN0bXQgPSAiVVBEQVRFIHt7Lk1vZGVsLlRhYmxlTmFtZX19IFNFVCB7eyAuIHwgdXBkYXRlX3ZhbHVlcyB9fSBXSEVSRSBpZCA9ID8iCiAgICByZXN1bHQsIGVyciA6PSBxdS5FeGVjKHN0bXQsIHt7IC4gfCB1cGRhdGVfYXJncyB9fSBpZCkKICAgIGlmIGVyciAhPSBuaWwgewogICAgICAgIHJldHVybiAwLCBlcnIKICAgIH0KICAgIHJldHVybiByZXN1bHQuUm93c0FmZmVjdGVkKCkKfQoKLy8gVXBzZXJ0IGluc2VydHMgYSBuZXcge3suTW9kZWwuTmFtZX19IHJvdyBpbiB0aGUge3suTW9kZWwuVGFibGVOYW1lfX0gdGFibGUKLy8gaWYgdGhlIHVuaXF1ZSBjb25zdHJhaW50cyBhcmUgbm90IGZvdW5kLCBvdGhlcndpc2UgaXQgdXBkYXRlcyBpdC4KZnVuYyAoe3suUmVjZWl2ZXJ9fSAqe3suTW9kZWwuTmFtZX19KSBVcHNlcnQocXUgUXVlcnllcikgKGxhc3RJbnNlcnRJRCBpbnQ2NCwgZXJyIGVycm9yKSB7CiAgICBjb25zdCBzdG10ID0gIklOU0VSVCBJTlRPIHt7Lk1vZGVsLlRhYmxlTmFtZX19ICh7ey5Nb2RlbC5GaWVsZHMgfCB1cHNlcnRfZmllbGRzfX0pIFZBTFVFUyAoe3suTW9kZWwuRmllbGRzIHwgdXBzZXJ0X3ZhbHVlc319KSBPTiBEVVBMSUNBVEUgS0VZIFVQREFURSB7eyAuIHwgdXBzZXJ0X29uX2R1cGxpY2F0ZSB9fSIKICAgIHJlcywgZXJyIDo9IHF1LkV4ZWMoc3RtdCwge3sgLiB8IHVwc2VydF9hcmdzIH19KQogICAgaWYgZXJyICE9IG5pbCB7CiAgICAgICAgcmV0dXJuIDAsIGVycgogICAgfQogICAgcmV0dXJuIHJlcy5MYXN0SW5zZXJ0SWQoKQp9CgovLyBGaW5kIGFuIGV4aXN0aW5nIHt7Lk1vZGVsLk5hbWV9fSByb3cgaW4gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlCmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgRmluZChxdSBRdWVyeWVyLCBpZCBpbnQ2NCkgZXJyb3IgewogICAgY29uc3Qgc3RtdCA9ICJTRUxFQ1QgKiBGUk9NIHt7Lk1vZGVsLlRhYmxlTmFtZX19IFdIRVJFIGlkID0gPyIKICAgIHJvdyA6PSBxdS5RdWVyeVJvdyhzdG10LCBpZCkKICAgIHJldHVybiByb3cuU2Nhbih7eyAuIHwgc2Nhbl9maWVsZHN9fSkKfQoKLy8gTG9hZCBhbGwsIG9yIGEgc3Vic2V0IG9mIHt7Lk1vZGVsLk5hbWV9fSByb3dzIGZyb20gdGhlIHt7Lk1vZGVsLlRhYmxlTmFtZX19IHRhYmxlCmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgTG9hZChxdSBRdWVyeWVyKSAoc2V0IFtde3suTW9kZWwuTmFtZX19LCBlcnIgZXJyb3IpIHsKICAgIHN0bXQgOj0gIlNFTEVDVCAqIEZST00ge3suTW9kZWwuVGFibGVOYW1lfX0iCgogICAgaWYge3suUmVjZWl2ZXJ9fS5saW1pdCA9PSAwICYmIHt7LlJlY2VpdmVyfX0ub2Zmc2V0ID4gMCB7CiAgICAgICAgcmV0dXJuIHNldCwgZm10LkVycm9yZigiY2Fubm90IHF1ZXJ5IHdpdGggb2Zmc2V0IGJ1dCBubyBsaW1pdCIpCiAgICB9CgogICAgaWYge3suUmVjZWl2ZXJ9fS5saW1pdCA+IDAgewogICAgICAgIHN0bXQgKz0gZm10LlNwcmludGYoIiBMSU1JVCAlZCIsIHt7LlJlY2VpdmVyfX0ubGltaXQpCiAgICB9CiAgICBpZiB7ey5SZWNlaXZlcn19Lm9mZnNldCA+IDAgewogICAgICAgIHN0bXQgKz0gZm10LlNwcmludGYoIiBPRkZTRVQgJWQiLCB7ey5SZWNlaXZlcn19Lm9mZnNldCkKICAgIH0KICAgIGRlZmVyIGZ1bmMoKSB7CiAgICAgICAge3suUmVjZWl2ZXJ9fS5saW1pdCA9IDAKICAgICAgICB7ey5SZWNlaXZlcn19Lm9mZnNldCA9IDAKICAgIH0oKQogICAgcm93cywgZXJyIDo9IHF1LlF1ZXJ5KHN0bXQpCiAgICBpZiBlcnIgIT0gbmlsIHsKICAgICAgICByZXR1cm4KICAgIH0KICAgIGRlZmVyIHJvd3MuQ2xvc2UoKQogICAgICAgIGZvciByb3dzLk5leHQoKSB7CiAgICAgICAgICAgIHZhciB7ey5SZWNlaXZlcn19IHt7Lk1vZGVsLk5hbWV9fQogICAgICAgICAgICBpZiBlcnIgPSByb3dzLlNjYW4oe3suIHwgc2Nhbl9maWVsZHN9fSk7IGVyciAhPSBuaWwgewogICAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgc2V0ID0gYXBwZW5kKHNldCwge3suUmVjZWl2ZXJ9fSkKICAgIH0KCiAgICByZXR1cm4KfQoKLy8gRGVsZXRlIGFuIGV4aXN0aW5nIHt7Lk1vZGVsLk5hbWV9fSByb3cgZnJvbSB0aGUge3suTW9kZWwuVGFibGVOYW1lfX0gdGFibGUKZnVuYyAoe3suUmVjZWl2ZXJ9fSAqe3suTW9kZWwuTmFtZX19KSBEZWxldGUocXUgUXVlcnllciwgaWQgaW50NjQpIChyb3dzQWZmZWN0ZWQgaW50NjQsIGVyciBlcnJvcikgewogICAgY29uc3Qgc3RtdCA9ICJERUxFVEUgRlJPTSB7ey5Nb2RlbC5UYWJsZU5hbWV9fSBXSEVSRSBpZCA9ID8iCiAgICByZXN1bHQsIGVyciA6PSBxdS5FeGVjKHN0bXQsIGlkKQoJaWYgZXJyICE9IG5pbCB7CgkJcmV0dXJuCgl9CgoJcmV0dXJuIHJlc3VsdC5Sb3dzQWZmZWN0ZWQoKQp9CgovLyBDb3VudCB0aGUgbnVtYmVyIG9mIHJvd3MgZnJvbSB0aGUge3suTW9kZWwuVGFibGVOYW1lfX0gdGFibGUKZnVuYyh7ey5SZWNlaXZlcn19ICp7ey5Nb2RlbC5OYW1lfX0pIENvdW50KHF1IFF1ZXJ5ZXIpIChjb3VudCBpbnQ2NCwgZXJyIGVycm9yKSB7CiAgICBjb25zdCBzdG10ID0gIlNFTEVDVCBDT1VOVCgqKSBGUk9NIHt7Lk1vZGVsLlRhYmxlTmFtZX19IgogICAgcm93IDo9IHF1LlF1ZXJ5Um93KHN0bXQpCiAgICBpZiBlcnIgPSByb3cuU2NhbigmY291bnQpOyBlcnIgIT0gbmlsIHsKICAgICAgICByZXR1cm4KICAgIH0KICAgIHJldHVybgp9CgovLyBFeGlzdHMgY2hlY2tzIGZvciB0aGUgaXRlbXMgZXhpc3RlbmNlIGluIHRoZSBkYXRhYmFzZSwgYmFzZWQgb24gaXQncyBpZC4KLy8gQW4gZXJyb3Igd2lsbCBvbmx5IGJlIHJldHVybmVkIGlmIGEgU1FMIHJlbGF0ZWQgZmFpbHVyZSBoYXBwZW5zLgovLyBJbiBhbGwgb3RoZXIgY2FzZXMsIGEgYm9vbCBhbmQgbmlsIHdpbGwgcmV0dXJuLgpmdW5jKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgRXhpc3RzKHF1IFF1ZXJ5ZXIsIGlkIGludDY0KSAoZXhpc3RzIGJvb2wsIGVyciBlcnJvcikgewogICAgY29uc3Qgc3RtdCA9ICJTRUxFQ1QgRVhJU1RTKFNFTEVDVCAxIEZST00ge3suTW9kZWwuVGFibGVOYW1lfX0gV0hFUkUgaWQgPSA/IExJTUlUIDEpIEFTIGBleGlzdHNgIgogICAgdmFyIGNvdW50IGludAogICAgcm93IDo9IHF1LlF1ZXJ5Um93KHN0bXQsIGlkKQogICAgaWYgZXJyID0gcm93LlNjYW4oJmNvdW50KTsgZXJyICE9IG5pbCB7CiAgICAgICAgcmV0dXJuCiAgICB9CiAgICByZXR1cm4gY291bnQgPiAwLCBuaWwKfQoKLy8gVGFibGVOYW1lIHJldHVybnMgdGhlIHRhYmxlIG5hbWUKZnVuYyAoe3suUmVjZWl2ZXJ9fSAqe3suTW9kZWwuTmFtZX19KSBUYWJsZU5hbWUoKSBzdHJpbmcgewpyZXR1cm4gInt7Lk1vZGVsLlRhYmxlTmFtZX19Igp9CgovLyBTZXRMaW1pdCBzZXRzIHRoZSBxdWVyeSBsaW1pdApmdW5jICh7ey5SZWNlaXZlcn19ICp7ey5Nb2RlbC5OYW1lfX0pIFNldExpbWl0KGxpbWl0IGludCkgKnt7Lk1vZGVsLk5hbWV9fSB7Cnt7LlJlY2VpdmVyfX0ubGltaXQgPSBsaW1pdApyZXR1cm4ge3suUmVjZWl2ZXJ9fQp9CgovLyBTZXRPZmZzZXQgc2V0cyB0aGUgcXVlcnkgb2Zmc2V0CmZ1bmMgKHt7LlJlY2VpdmVyfX0gKnt7Lk1vZGVsLk5hbWV9fSkgU2V0T2Zmc2V0KG9mZnNldCBpbnQpICp7ey5Nb2RlbC5OYW1lfX0gewp7ey5SZWNlaXZlcn19Lm9mZnNldCA9IG9mZnNldApyZXR1cm4ge3suUmVjZWl2ZXJ9fQp9Cnt7ZW5kfX0KCg==\"") + packr.PackJSONBytes("./tmpl", "tmpl.go", "\"cGFja2FnZSB0bXBsCgppbXBvcnQgKAoJImZtdCIKCSJodG1sL3RlbXBsYXRlIgoJInN0cmluZ3MiCikKCnZhciBGdW5jTWFwID0gdGVtcGxhdGUuRnVuY01hcHsKCSJpbnNlcnRfZmllbGRzIjogICAgICAgR2V0SW5zZXJ0RmllbGRzLAoJImluc2VydF92YWx1ZXMiOiAgICAgICBHZXRJbnNlcnRWYWx1ZXMsCgkiaW5zZXJ0X2FyZ3MiOiAgICAgICAgIEdldEluc2VydEFyZ3MsCgkic2Nhbl9maWVsZHMiOiAgICAgICAgIEdldFNjYW5GaWVsZHMsCgkidXBkYXRlX2FyZ3MiOiAgICAgICAgIEdldFVwZGF0ZUFyZ3MsCgkidXBkYXRlX3ZhbHVlcyI6ICAgICAgIEdldFVwZGF0ZVZhbHVlcywKCSJ1cHNlcnRfZmllbGRzIjogICAgICAgR2V0VXBzZXJ0RmllbGRzLAoJInVwc2VydF92YWx1ZXMiOiAgICAgICBHZXRVcHNlcnRWYWx1ZXMsCgkidXBzZXJ0X29uX2R1cGxpY2F0ZSI6IEdldFVwc2VydE9uRHVwbGljYXRlLAoJInVwc2VydF9hcmdzIjogICAgICAgICBHZXRVcHNlcnRBcmdzLAp9CgpmdW5jIEdldEluc2VydEZpZWxkcyhmaWVsZHMgW11UbXBsRmllbGQpIHN0cmluZyB7Cgl2YXIgcGFydHMgW11zdHJpbmcKCWZvciBfLCBmbCA6PSByYW5nZSBmaWVsZHMgewoJCWlmIGZsLkNvbHVtbk5hbWUgPT0gImlkIiB7CgkJCWNvbnRpbnVlCgkJfQoJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCAiYCIrZmwuQ29sdW1uTmFtZSsiYCIpCgl9CglyZXR1cm4gc3RyaW5ncy5Kb2luKHBhcnRzLCAiLCAiKQp9CgpmdW5jIEdldEluc2VydFZhbHVlcyhmaWVsZHMgW11UbXBsRmllbGQpIHN0cmluZyB7Cgl2YXIgcGFydHMgW11zdHJpbmcKCWZvciBfLCBmbCA6PSByYW5nZSBmaWVsZHMgewoJCXN3aXRjaCBmbC5Db2x1bW5OYW1lIHsKCQljYXNlICJpZCI6CgkJCWNvbnRpbnVlCgkJY2FzZSAiY3JlYXRlZF9hdCI6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCAiTk9XKCkiKQoJCQljb250aW51ZQoJCWRlZmF1bHQ6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCAiPyIpCgkJfQoJfQoJcmV0dXJuIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKfQoKZnVuYyBHZXRJbnNlcnRBcmdzKG0gU3RydWN0VG1wbERhdGEpIHN0cmluZyB7Cgl2YXIgcGFydHMgW11zdHJpbmcKCWZvciBfLCBmbCA6PSByYW5nZSBtLk1vZGVsLkZpZWxkcyB7CgkJc3dpdGNoIGZsLk5hbWUgewoJCWNhc2UgIklEIiwgIkNyZWF0ZWRBdCI6CgkJCWNvbnRpbnVlCgkJfQoJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiJXMuJXMiLCBtLlJlY2VpdmVyLCBmbC5OYW1lKSkKCX0KCWlmIGxlbihwYXJ0cykgPiAwIHsKCQlyZXR1cm4gIiwgIiArIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKCX0KCXJldHVybiAiIgp9CgpmdW5jIEdldFNjYW5GaWVsZHMobSBTdHJ1Y3RUbXBsRGF0YSkgdGVtcGxhdGUuSFRNTCB7Cgl2YXIgcGFydHMgW11zdHJpbmcKCWZvciBfLCBmbCA6PSByYW5nZSBtLk1vZGVsLkZpZWxkcyB7CgkJcGFydHMgPSBhcHBlbmQocGFydHMsIGZtdC5TcHJpbnRmKCImJXMuJXMiLCBtLlJlY2VpdmVyLCBmbC5OYW1lKSkKCX0KCXJldHVybiB0ZW1wbGF0ZS5IVE1MKHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikpCn0KCmZ1bmMgR2V0VXBkYXRlQXJncyhtIFN0cnVjdFRtcGxEYXRhKSB0ZW1wbGF0ZS5IVE1MIHsKCXZhciBwYXJ0cyBbXXN0cmluZwoJZm9yIF8sIGZsIDo9IHJhbmdlIG0uTW9kZWwuRmllbGRzIHsKCQlzd2l0Y2ggZmwuTmFtZSB7CgkJY2FzZSAiSUQiLCAiQ3JlYXRlZEF0IiwgIlVwZGF0ZWRBdCI6CgkJCWNvbnRpbnVlCgkJfQoJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiJXMuJXMiLCBtLlJlY2VpdmVyLCBmbC5OYW1lKSkKCX0KCWlmIGxlbihwYXJ0cykgPiAwIHsKCQlyZXR1cm4gdGVtcGxhdGUuSFRNTChzdHJpbmdzLkpvaW4ocGFydHMsICIsICIpICsgIiwgIikKCX0KCXJldHVybiAiIgp9CgpmdW5jIEdldFVwZGF0ZVZhbHVlcyhtIFN0cnVjdFRtcGxEYXRhKSBzdHJpbmcgewoJdmFyIHBhcnRzIFtdc3RyaW5nCglmb3IgXywgZmwgOj0gcmFuZ2UgbS5Nb2RlbC5GaWVsZHMgewoJCXN3aXRjaCBmbC5OYW1lIHsKCQljYXNlICJJRCIsICJDcmVhdGVkQXQiOgoJCQljb250aW51ZQoJCWNhc2UgIlVwZGF0ZWRBdCI6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiYCVzYD1VVENfVElNRVNUQU1QKCkiLCBmbC5Db2x1bW5OYW1lKSkKCQlkZWZhdWx0OgoJCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgZm10LlNwcmludGYoImAlc2A9PyIsIGZsLkNvbHVtbk5hbWUpKQoJCX0KCX0KCXJldHVybiBzdHJpbmdzLkpvaW4ocGFydHMsICIsICIpCn0KCmZ1bmMgR2V0VXBzZXJ0RmllbGRzKGZpZWxkcyBbXVRtcGxGaWVsZCkgc3RyaW5nIHsKCXZhciBwYXJ0cyBbXXN0cmluZwoJZm9yIF8sIGZsIDo9IHJhbmdlIGZpZWxkcyB7CgkJcGFydHMgPSBhcHBlbmQocGFydHMsICJgIitmbC5Db2x1bW5OYW1lKyJgIikKCX0KCXJldHVybiBzdHJpbmdzLkpvaW4ocGFydHMsICIsICIpCn0KCmZ1bmMgR2V0VXBzZXJ0VmFsdWVzKGZpZWxkcyBbXVRtcGxGaWVsZCkgc3RyaW5nIHsKCXZhciBwYXJ0cyBbXXN0cmluZwoJZm9yIF8sIGZsIDo9IHJhbmdlIGZpZWxkcyB7CgkJc3dpdGNoIGZsLkNvbHVtbk5hbWUgewoJCWNhc2UgImNyZWF0ZWRfYXQiOgoJCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgIk5PVygpIikKCQkJY29udGludWUKCQlkZWZhdWx0OgoJCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgIj8iKQoJCX0KCX0KCXJldHVybiBzdHJpbmdzLkpvaW4ocGFydHMsICIsICIpCn0KCmZ1bmMgR2V0VXBzZXJ0T25EdXBsaWNhdGUobSBTdHJ1Y3RUbXBsRGF0YSkgc3RyaW5nIHsKCXZhciBwYXJ0cyBbXXN0cmluZwoJZm9yIF8sIGZsIDo9IHJhbmdlIG0uTW9kZWwuRmllbGRzIHsKCQlzd2l0Y2ggZmwuTmFtZSB7CgkJY2FzZSAiQ3JlYXRlZEF0IjoKCQkJY29udGludWUKCQljYXNlICJJRCI6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiYCVzYD1MQVNUX0lOU0VSVF9JRChgJXNgKSIsIGZsLkNvbHVtbk5hbWUsIGZsLkNvbHVtbk5hbWUpKQoJCWNhc2UgIlVwZGF0ZWRBdCI6CgkJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiYCVzYD1VVENfVElNRVNUQU1QKCkiLCBmbC5Db2x1bW5OYW1lKSkKCQlkZWZhdWx0OgoJCQlwYXJ0cyA9IGFwcGVuZChwYXJ0cywgZm10LlNwcmludGYoImAlc2A9VkFMVUVTKGAlc2ApIiwgZmwuQ29sdW1uTmFtZSwgZmwuQ29sdW1uTmFtZSkpCgkJfQoJfQoJcmV0dXJuIHN0cmluZ3MuSm9pbihwYXJ0cywgIiwgIikKfQoKZnVuYyBHZXRVcHNlcnRBcmdzKG0gU3RydWN0VG1wbERhdGEpIHN0cmluZyB7Cgl2YXIgcGFydHMgW11zdHJpbmcKCWZvciBfLCBmbCA6PSByYW5nZSBtLk1vZGVsLkZpZWxkcyB7CgkJc3dpdGNoIGZsLk5hbWUgewoJCWNhc2UgIkNyZWF0ZWRBdCI6CgkJCWNvbnRpbnVlCgkJfQoJCXBhcnRzID0gYXBwZW5kKHBhcnRzLCBmbXQuU3ByaW50ZigiJXMuJXMiLCBtLlJlY2VpdmVyLCBmbC5OYW1lKSkKCX0KCXJldHVybiBzdHJpbmdzLkpvaW4ocGFydHMsICIsICIpCn0K\"") packr.PackJSONBytes("./tmpl", "types.go", "\"cGFja2FnZSB0bXBsCgovLyBUbXBsU3RydWN0cyBpcyBhIGNvbGxlY3Rpb24gb24gVG1wbFN0cnVjdAp0eXBlIFRtcGxTdHJ1Y3RzIFtdVG1wbFN0cnVjdAoKLy8gVG1wbFN0cnVjdCBkZWZpbmVzIHRoZSB0YWJsZSBkYXRhIHRvIHBhc3MgdG8gdGhlIG1vZGVscwp0eXBlIFRtcGxTdHJ1Y3Qgc3RydWN0IHsKCU5hbWUgICAgICBzdHJpbmcKCVRhYmxlTmFtZSBzdHJpbmcKCUZpZWxkcyAgICBbXVRtcGxGaWVsZAoJSW1wb3J0cyAgIG1hcFtzdHJpbmddc3RydWN0e30KfQoKLy8gVG1wbEZpZWxkIGRlZmluZXMgYSB0YWJsZSBmaWVsZCB0ZW1wbGF0ZQp0eXBlIFRtcGxGaWVsZCBzdHJ1Y3QgewoJTmFtZSAgICAgICBzdHJpbmcKCVR5cGUgICAgICAgc3RyaW5nCglDb2x1bW5OYW1lIHN0cmluZwoJTnVsbGFibGUgICBib29sCn0KCi8vIFN0cnVjdFRtcGxEYXRhIGRlZmluZXMgdGhlIHRvcCBsZXZlbCBzdHJ1Y3QgZGF0YSB0byBwYXNzIHRvIHRoZSBtb2RlbHMKdHlwZSBTdHJ1Y3RUbXBsRGF0YSBzdHJ1Y3QgewoJTW9kZWwgICAgICAgVG1wbFN0cnVjdAoJUmVjZWl2ZXIgICAgc3RyaW5nCglQYWNrYWdlTmFtZSBzdHJpbmcKfQo=\"") packr.PackJSONBytes("./tmpl", "x_helpers.html", "\"e3tkZWZpbmUgImhlbHBlcnMifX0KCnBhY2thZ2Uge3sgLlBhY2thZ2VOYW1lIH19CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCBDb2RlIGdlbmVyYXRlZCBieSBtb2RlbGdlbiB8CnwgICAgICAgIERPIE5PVCBFRElULiAgICAgICAgfAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KCmltcG9ydCAoCgkiYnl0ZXMiCgkiY29udGV4dCIKCSJkYXRhYmFzZS9zcWwiCgkiZGF0YWJhc2Uvc3FsL2RyaXZlciIKCSJlbmNvZGluZy9qc29uIgoJImZtdCIKCSJsb2ciCgkicmVmbGVjdCIKCSJzdHJpbmdzIgoJInRpbWUiCgoJImdpdGh1Yi5jb20vZ28tc3FsLWRyaXZlci9teXNxbCIKKQoKLy8gU3RkVGltZSBwcm92aWRlcyBkZWZhdWx0IFNRTCBUSU1FIGZvcm1hdApjb25zdCBTdGRUaW1lID0gIjE1OjA0OjA1IgoKLy8gZW1wdHlUaW1lIGFsbG93cyBkZWZhdWx0IHRpbWVzIHRvIGJlIGNvbnNpZGVyZWQKLy8gbnVsbCBmb3IgaW5zZXJ0aW9uIGludG8gdGhlIGRhdGFiYXNlLgp2YXIgZW1wdHlUaW1lID0gdGltZS5UaW1le30KCi8vIG51bGxMaXRlcmFsIGlzIGhlbHBmdWwgZm9yIGNoZWNraW5nCi8vIGZvciBudWxscywgYXMgdGhleSB3b24ndCBjYXVzZSBlcnJvcnMsCi8vIHlldCB3ZSBuZWVkIHRoZSBjb250ZW50IG9mIHRoZSBmaWxlIHRvIGNoYW5nZSBhbnl3YXkKdmFyIG51bGxMaXRlcmFsID0gW11ieXRlKCJudWxsIikKCi8qKioqKioqKgoqIFR5cGVzICoKKioqKioqKiovCgovLyBRdWVyeWVyIGFsbG93cyBzcWwuREIgYW5kIHNxbC5UeCB0byBiZSB1c2VkIGludGVyY2hhbmdlYWJseSwgYWxsb3dpbmcgeW91Ci8vIHRvIHVzZSBhbnkgb2YgdGhlIG1vZGVsIG1ldGhvZHMgaW5zaWRlIHRyYW5zYWN0aW9ucyBvciBzdGFuZGFsb25lIGNhbGxzLgp0eXBlIFF1ZXJ5ZXIgaW50ZXJmYWNlIHsKCVF1ZXJ5KHF1ZXJ5IHN0cmluZywgYXJncyAuLi5pbnRlcmZhY2V7fSkgKCpzcWwuUm93cywgZXJyb3IpCglRdWVyeVJvdyhxdWVyeSBzdHJpbmcsIGFyZ3MgLi4uaW50ZXJmYWNle30pICpzcWwuUm93CglFeGVjKHF1ZXJ5IHN0cmluZywgYXJncyAuLi5pbnRlcmZhY2V7fSkgKHNxbC5SZXN1bHQsIGVycm9yKQp9CgovKi0tLS0tLS0tLS0tLS0rCnwgVHlwZSBhbGlhc2VzIHwKKy0tLS0tLS0tLS0tLS0qLwoKLy8gTnVsbEZsb2F0NjQgYWxpYXNlcyBzcWwuTnVsbEZsb2F0NjQKdHlwZSBOdWxsRmxvYXQ2NCBzcWwuTnVsbEZsb2F0NjQKCi8vIE51bGxTdHJpbmcgYWxpYXNlcyBzcWwuTnVsbFN0cmluZwp0eXBlIE51bGxTdHJpbmcgc3FsLk51bGxTdHJpbmcKCi8vIE51bGxCb29sIGFsaWFzZXMgc3FsLk51bGxCb29sCnR5cGUgTnVsbEJvb2wgc3FsLk51bGxCb29sCgovLyBOdWxsSW50NjQgYWxpYXNlcyBzcWwuTnVsbEludDY0CnR5cGUgTnVsbEludDY0IHNxbC5OdWxsSW50NjQKCi8vIE51bGxUaW1lIGFsaWFzZXMgc3FsLk51bGxUaW1lCnR5cGUgTnVsbFRpbWUgbXlzcWwuTnVsbFRpbWUKCi8vIFJhd0pTT04gYWxpYXNlcyBqc29uLlJhd01lc3NhZ2UKdHlwZSBSYXdKU09OIGpzb24uUmF3TWVzc2FnZQoKLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCnwgTnVsbFN0cmluZyBpbXBsZW1lbnRhdGlvbnMgfAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KCi8vIE1hcnNoYWxKU09OIGZvciBOdWxsU3RyaW5nCmZ1bmMgKG4gTnVsbFN0cmluZykgTWFyc2hhbEpTT04oKSAoW11ieXRlLCBlcnJvcikgewoJdmFyIGEgKnN0cmluZwoJaWYgbi5WYWxpZCB7CgkJYSA9ICZuLlN0cmluZwoJfQoJcmV0dXJuIGpzb24uTWFyc2hhbChhKQp9CgovLyBVbm1hcnNoYWxKU09OIGZvciBOdWxsU3RyaW5nCmZ1bmMgKG4gKk51bGxTdHJpbmcpIFVubWFyc2hhbEpTT04oYiBbXWJ5dGUpIGVycm9yIHsKCWlmIGJ5dGVzLkVxdWFsRm9sZChiLCBudWxsTGl0ZXJhbCkgewoJCW4uVmFsaWQgPSBmYWxzZQoJCXJldHVybiBuaWwKCX0KCWVyciA6PSBqc29uLlVubWFyc2hhbChiLCAmbi5TdHJpbmcpCgluLlZhbGlkID0gZXJyID09IG5pbAoJcmV0dXJuIGVycgp9CgovLyBWYWx1ZSBmb3IgTnVsbFN0cmluZwpmdW5jIChuIE51bGxTdHJpbmcpIFZhbHVlKCkgKGRyaXZlci5WYWx1ZSwgZXJyb3IpIHsKCWlmICFuLlZhbGlkIHsKCQlyZXR1cm4gbmlsLCBuaWwKCX0KCXJldHVybiBuLlN0cmluZywgbmlsCn0KCi8vIFNjYW4gZm9yIE51bGxTdHJpbmcKZnVuYyAobiAqTnVsbFN0cmluZykgU2NhbihzcmMgaW50ZXJmYWNle30pIGVycm9yIHsKCXZhciBhIHNxbC5OdWxsU3RyaW5nCglpZiBlcnIgOj0gYS5TY2FuKHNyYyk7IGVyciAhPSBuaWwgewoJCXJldHVybiBlcnIKCX0KCW4uU3RyaW5nID0gYS5TdHJpbmcKCWlmIHJlZmxlY3QuVHlwZU9mKHNyYykgIT0gbmlsIHsKCQluLlZhbGlkID0gdHJ1ZQoJfQoJcmV0dXJuIG5pbAp9CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCnwgTnVsbEZsb2F0NjQgaW1wbGVtZW50YXRpb25zIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwoKLy8gTWFyc2hhbEpTT04gZm9yIE51bGxGbG9hdDY0CmZ1bmMgKG4gTnVsbEZsb2F0NjQpIE1hcnNoYWxKU09OKCkgKFtdYnl0ZSwgZXJyb3IpIHsKCXZhciBhICpmbG9hdDY0CglpZiBuLlZhbGlkIHsKCQlhID0gJm4uRmxvYXQ2NAoJfQoJcmV0dXJuIGpzb24uTWFyc2hhbChhKQp9CgovLyBWYWx1ZSBmb3IgTnVsbEZsb2F0NjQKZnVuYyAobiBOdWxsRmxvYXQ2NCkgVmFsdWUoKSAoZHJpdmVyLlZhbHVlLCBlcnJvcikgewoJaWYgIW4uVmFsaWQgewoJCXJldHVybiBuaWwsIG5pbAoJfQoJcmV0dXJuIG4uRmxvYXQ2NCwgbmlsCn0KCi8vIFVubWFyc2hhbEpTT04gZm9yIE51bGxGbG9hdDY0CmZ1bmMgKG4gKk51bGxGbG9hdDY0KSBVbm1hcnNoYWxKU09OKGIgW11ieXRlKSBlcnJvciB7CglpZiBieXRlcy5FcXVhbEZvbGQoYiwgbnVsbExpdGVyYWwpIHsKCQluLlZhbGlkID0gZmFsc2UKCQlyZXR1cm4gbmlsCgl9CgllcnIgOj0ganNvbi5Vbm1hcnNoYWwoYiwgJm4uRmxvYXQ2NCkKCW4uVmFsaWQgPSBlcnIgPT0gbmlsCglyZXR1cm4gZXJyCn0KCi8vIFNjYW4gZm9yIE51bGxGbG9hdDY0CmZ1bmMgKG4gKk51bGxGbG9hdDY0KSBTY2FuKHNyYyBpbnRlcmZhY2V7fSkgZXJyb3IgewoJdmFyIGEgc3FsLk51bGxGbG9hdDY0CglpZiBlcnIgOj0gYS5TY2FuKHNyYyk7IGVyciAhPSBuaWwgewoJCXJldHVybiBlcnIKCX0KCW4uRmxvYXQ2NCA9IGEuRmxvYXQ2NAoJaWYgcmVmbGVjdC5UeXBlT2Yoc3JjKSAhPSBuaWwgewoJCW4uVmFsaWQgPSB0cnVlCgl9CglyZXR1cm4gbmlsCn0KCi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCnwgTnVsbEludDY0IGltcGxlbWVudGF0aW9ucyB8CistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCgovLyBNYXJzaGFsSlNPTiBmb3IgTnVsbEludDY0CmZ1bmMgKG4gTnVsbEludDY0KSBNYXJzaGFsSlNPTigpIChbXWJ5dGUsIGVycm9yKSB7Cgl2YXIgYSAqaW50NjQKCWlmIG4uVmFsaWQgewoJCWEgPSAmbi5JbnQ2NAoJfQoJcmV0dXJuIGpzb24uTWFyc2hhbChhKQp9CgovLyBWYWx1ZSBmb3IgTnVsbEludDY0CmZ1bmMgKG4gTnVsbEludDY0KSBWYWx1ZSgpIChkcml2ZXIuVmFsdWUsIGVycm9yKSB7CglpZiAhbi5WYWxpZCB7CgkJcmV0dXJuIG5pbCwgbmlsCgl9CglyZXR1cm4gbi5JbnQ2NCwgbmlsCn0KCi8vIFVubWFyc2hhbEpTT04gZm9yIE51bGxJbnQ2NApmdW5jIChuICpOdWxsSW50NjQpIFVubWFyc2hhbEpTT04oYiBbXWJ5dGUpIGVycm9yIHsKCWlmIGJ5dGVzLkVxdWFsRm9sZChiLCBudWxsTGl0ZXJhbCkgewoJCW4uVmFsaWQgPSBmYWxzZQoJCXJldHVybiBuaWwKCX0KCWVyciA6PSBqc29uLlVubWFyc2hhbChiLCAmbi5JbnQ2NCkKCW4uVmFsaWQgPSBlcnIgPT0gbmlsCglyZXR1cm4gZXJyCn0KCi8vIFNjYW4gZm9yIE51bGxJbnQ2NApmdW5jIChuICpOdWxsSW50NjQpIFNjYW4oc3JjIGludGVyZmFjZXt9KSBlcnJvciB7CgkvLyBTZXQgaW5pdGlhbCBzdGF0ZSBmb3Igc3Vic2VxdWVudCBzY2Fucy4KCW4uVmFsaWQgPSBmYWxzZQoKCXZhciBhIHNxbC5OdWxsSW50NjQKCWlmIGVyciA6PSBhLlNjYW4oc3JjKTsgZXJyICE9IG5pbCB7CgkJcmV0dXJuIGVycgoJfQoJbi5JbnQ2NCA9IGEuSW50NjQKCWlmIHJlZmxlY3QuVHlwZU9mKHNyYykgIT0gbmlsIHsKCQluLlZhbGlkID0gdHJ1ZQoJfQoJcmV0dXJuIG5pbAp9CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCnwgTnVsbEJvb2wgaW1wbGVtZW50YXRpb25zIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwoKLy8gTWFyc2hhbEpTT04gZm9yIE51bGxCb29sCmZ1bmMgKG4gTnVsbEJvb2wpIE1hcnNoYWxKU09OKCkgKFtdYnl0ZSwgZXJyb3IpIHsKCXZhciBhICpib29sCglpZiBuLlZhbGlkIHsKCQlhID0gJm4uQm9vbAoJfQoJcmV0dXJuIGpzb24uTWFyc2hhbChhKQp9CgovLyBWYWx1ZSBmb3IgTnVsbEJvb2wKZnVuYyAobiBOdWxsQm9vbCkgVmFsdWUoKSAoZHJpdmVyLlZhbHVlLCBlcnJvcikgewoJaWYgIW4uVmFsaWQgewoJCXJldHVybiBuaWwsIG5pbAoJfQoJcmV0dXJuIG4uQm9vbCwgbmlsCn0KCi8vIFVubWFyc2hhbEpTT04gZm9yIE51bGxCb29sCmZ1bmMgKG4gKk51bGxCb29sKSBVbm1hcnNoYWxKU09OKGIgW11ieXRlKSBlcnJvciB7Cgl2YXIgZmllbGQgKmJvb2wKCWVyciA6PSBqc29uLlVubWFyc2hhbChiLCAmZmllbGQpCglpZiBmaWVsZCAhPSBuaWwgewoJCW4uVmFsaWQgPSB0cnVlCgkJbi5Cb29sID0gKmZpZWxkCgl9CglyZXR1cm4gZXJyCn0KCi8vIFNjYW4gZm9yIE51bGxCb29sCmZ1bmMgKG4gKk51bGxCb29sKSBTY2FuKHNyYyBpbnRlcmZhY2V7fSkgZXJyb3IgewoJdmFyIGEgc3FsLk51bGxCb29sCglpZiBlcnIgOj0gYS5TY2FuKHNyYyk7IGVyciAhPSBuaWwgewoJCXJldHVybiBlcnIKCX0KCW4uQm9vbCA9IGEuQm9vbAoJaWYgcmVmbGVjdC5UeXBlT2Yoc3JjKSAhPSBuaWwgewoJCW4uVmFsaWQgPSB0cnVlCgl9CglyZXR1cm4gbmlsCn0KCi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCBOdWxsVGltZSBpbXBsZW1lbnRhdGlvbnMgfAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCgovLyBNYXJzaGFsSlNPTiBmb3IgTnVsbFRpbWUKZnVuYyAobiBOdWxsVGltZSkgTWFyc2hhbEpTT04oKSAoW11ieXRlLCBlcnJvcikgewoJdmFyIGEgKnRpbWUuVGltZQoJaWYgbi5WYWxpZCB7CgkJYSA9ICZuLlRpbWUKCX0KCXJldHVybiBqc29uLk1hcnNoYWwoYSkKfQoKLy8gVmFsdWUgZm9yIE51bGxUaW1lCmZ1bmMgKG4gTnVsbFRpbWUpIFZhbHVlKCkgKGRyaXZlci5WYWx1ZSwgZXJyb3IpIHsKCWlmICFuLlZhbGlkIHsKCQlyZXR1cm4gbmlsLCBuaWwKCX0KCXJldHVybiBuLlRpbWUsIG5pbAp9CgovLyBVbm1hcnNoYWxKU09OIGZvciBOdWxsVGltZQpmdW5jIChuICpOdWxsVGltZSkgVW5tYXJzaGFsSlNPTihiIFtdYnl0ZSkgZXJyb3IgewogICAgcyA6PSBzdHJpbmcoYikKICAgIHMgPSBzdHJpbmdzLlRyaW0ocywgYCJgKQoKICAgIHZhciAoCiAgICAgICAgemVyb1RpbWUgdGltZS5UaW1lCiAgICAgICAgdGltICAgICAgdGltZS5UaW1lCiAgICAgICAgZXJyICAgICAgZXJyb3IKICAgICkKCiAgICBpZiBzdHJpbmdzLkVxdWFsRm9sZChzLCAibnVsbCIpIHsKICAgICAgICByZXR1cm4gbmlsCiAgICB9CgogICAgaWYgdGltLCBlcnIgPSB0aW1lLlBhcnNlKHRpbWUuUkZDMzMzOSwgcyk7IGVyciAhPSBuaWwgewogICAgICAgIG4uVmFsaWQgPSBmYWxzZQogICAgICAgIHJldHVybiBlcnIKICAgIH0KCiAgICBpZiB0aW0gPT0gemVyb1RpbWUgewogICAgICAgIHJldHVybiBuaWwKICAgIH0KCiAgICBuLlRpbWUgPSB0aW0KICAgIG4uVmFsaWQgPSB0cnVlCiAgICByZXR1cm4gbmlsCn0KCi8vIFNjYW4gZm9yIE51bGxUaW1lCmZ1bmMgKG4gKk51bGxUaW1lKSBTY2FuKHNyYyBpbnRlcmZhY2V7fSkgZXJyb3IgewoJLy8gU2V0IGluaXRpYWwgc3RhdGUgZm9yIHN1YnNlcXVlbnQgc2NhbnMuCgluLlZhbGlkID0gZmFsc2UKCgl2YXIgYSBteXNxbC5OdWxsVGltZQoJaWYgZXJyIDo9IGEuU2NhbihzcmMpOyBlcnIgIT0gbmlsIHsKCQlyZXR1cm4gZXJyCgl9CgluLlRpbWUgPSBhLlRpbWUKCWlmIHJlZmxlY3QuVHlwZU9mKHNyYykgIT0gbmlsIHsKCQluLlZhbGlkID0gdHJ1ZQoJfQoJcmV0dXJuIG5pbAp9CgovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsKfCBSYXdKU09OIGltcGxlbWVudGF0aW9ucyB8CistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwoKLy8gTWFyc2hhbEpTT04gZm9yIE51bGxTdHJpbmcKZnVuYyAobiBSYXdKU09OKSBNYXJzaGFsSlNPTigpIChbXWJ5dGUsIGVycm9yKSB7CglpZiBsZW4obikgPT0gMCB7CgkJcmV0dXJuIFtdYnl0ZSgibnVsbCIpLCBuaWwKCX0KCWEgOj0ganNvbi5SYXdNZXNzYWdlKG4pCglyZXR1cm4gYS5NYXJzaGFsSlNPTigpCn0KCi8vIFZhbHVlIGZvciBOdWxsU3RyaW5nCmZ1bmMgKG4gUmF3SlNPTikgVmFsdWUoKSAoZHJpdmVyLlZhbHVlLCBlcnJvcikgewoJcmV0dXJuIHN0cmluZyhuKSwgbmlsCn0KCi8vIFVubWFyc2hhbEpTT04gZm9yIE51bGxTdHJpbmcKZnVuYyAobiAqUmF3SlNPTikgVW5tYXJzaGFsSlNPTihiIFtdYnl0ZSkgZXJyb3IgewoJdmFyIGEganNvbi5SYXdNZXNzYWdlCglpZiBlcnIgOj0ganNvbi5Vbm1hcnNoYWwoYiwgJmEpOyBlcnIgIT0gbmlsIHsKCQlyZXR1cm4gZXJyCgl9CgljIDo9IFJhd0pTT04oYSkKCSpuID0gYwoJcmV0dXJuIG5pbAp9CgovLyBTY2FuIGZvciBOdWxsU3RyaW5nCmZ1bmMgKG4gKlJhd0pTT04pIFNjYW4oc3JjIGludGVyZmFjZXt9KSBlcnJvciB7Cgl2YXIgYSBzcWwuTnVsbFN0cmluZwoJaWYgZXJyIDo9IGEuU2NhbihzcmMpOyBlcnIgIT0gbmlsIHsKCQlyZXR1cm4gZXJyCgl9Cglqc24gOj0gUmF3SlNPTihbXWJ5dGUoYS5TdHJpbmcpKQoJKm4gPSBqc24KCXJldHVybiBuaWwKfQoKLyotLS0tLS0tLS0tLS0tLS0tLSsKfCBIZWxwZXIgZnVuY3Rpb25zIHwKKy0tLS0tLS0tLS0tLS0tLS0tKi8KCi8vIFRvTnVsbFN0cmluZyByZXR1cm5zIGEgbmV3IE51bGxTdHJpbmcKZnVuYyBUb051bGxTdHJpbmcocyAqc3RyaW5nKSBOdWxsU3RyaW5nIHsKCWlmIHMgPT0gbmlsIHsKCQlyZXR1cm4gTnVsbFN0cmluZyhzcWwuTnVsbFN0cmluZ3tWYWxpZDogZmFsc2V9KQoJfQoJcmV0dXJuIE51bGxTdHJpbmcoc3FsLk51bGxTdHJpbmd7U3RyaW5nOiAqcywgVmFsaWQ6IHRydWV9KQp9CgovLyBUb051bGxJbnQ2NCByZXR1cm5zIGEgbmV3IE51bGxJbnQ2NApmdW5jIFRvTnVsbEludDY0KGkgKmludDY0KSBOdWxsSW50NjQgewoJaWYgaSA9PSBuaWwgewoJCXJldHVybiBOdWxsSW50NjQoc3FsLk51bGxJbnQ2NHtWYWxpZDogZmFsc2V9KQoJfQoJcmV0dXJuIE51bGxJbnQ2NChzcWwuTnVsbEludDY0e0ludDY0OiAqaSwgVmFsaWQ6IHRydWV9KQp9CgovLyBUb051bGxGbG9hdDY0IHJldHVybnMgYSBuZXcgTnVsbEZsb2F0NjQKZnVuYyBUb051bGxGbG9hdDY0KGkgKmZsb2F0NjQpIE51bGxGbG9hdDY0IHsKCWlmIGkgPT0gbmlsIHsKCQlyZXR1cm4gTnVsbEZsb2F0NjQoc3FsLk51bGxGbG9hdDY0e1ZhbGlkOiBmYWxzZX0pCgl9CglyZXR1cm4gTnVsbEZsb2F0NjQoc3FsLk51bGxGbG9hdDY0e0Zsb2F0NjQ6ICppLCBWYWxpZDogdHJ1ZX0pCn0KCi8vIFRvTnVsbEJvb2wgY3JlYXRlcyBhIG5ldyBOdWxsQm9vbApmdW5jIFRvTnVsbEJvb2woYiAqYm9vbCkgTnVsbEJvb2wgewoJaWYgYiA9PSBuaWwgewoJCXJldHVybiBOdWxsQm9vbChzcWwuTnVsbEJvb2x7VmFsaWQ6IGZhbHNlfSkKCX0KCXJldHVybiBOdWxsQm9vbChzcWwuTnVsbEJvb2x7Qm9vbDogKmIsIFZhbGlkOiB0cnVlfSkKfQoKLy8gVG9OdWxsVGltZSBjcmVhdGVzIGEgbmV3IE51bGxUaW1lCmZ1bmMgVG9OdWxsVGltZSh0IHRpbWUuVGltZSkgTnVsbFRpbWUgewoJaWYgdCA9PSBlbXB0eVRpbWUgewoJCXJldHVybiBOdWxsVGltZShteXNxbC5OdWxsVGltZXtWYWxpZDogZmFsc2V9KQoJfQoJcmV0dXJuIE51bGxUaW1lKG15c3FsLk51bGxUaW1le1RpbWU6IHQsIFZhbGlkOiB0cnVlfSkKfQoKLy8gVHhPcHRpb25zIGRlZmluZXMgYW4gb3B0aW9uIHR5cGUgZm9yIGNvbmZpZ3VyaW5nCi8vIHRyYW5zYXRpb25zLiBUaGlzIG1heSBvbmx5IGJlIHVzZWQgd2l0aCB0aGUgRXhlY3V0ZVRyYW5zYWN0aW9uIHdyYXBwZXIuCnR5cGUgVHhPcHRpb25zIHN0cnVjdCB7CglUaW1lb3V0ICAgdGltZS5EdXJhdGlvbgoJSXNvbGF0aW9uIHNxbC5Jc29sYXRpb25MZXZlbAoJUmVhZE9ubHkgIGJvb2wKfQoKLy8gRXhlY3V0ZVRyYW5zYWN0aW9uIGNsb3NlcyBvdmVyIGEgdHJhbnNhY3Rpb24gYW5kIGF1dG9tYXRpY2FsbHkgY29tbWl0cwovLyBvciByb2xsYmFja3MgZGVwZW5kaW5nIG9uIHdoZXRoZXIgZXJyb3JzIHdlcmUgZW5jb3VudGVyZWQuCi8vIEluIHRoZSBjYXNlIHdoZXJlIG5pbCBpcyBwYXNzZWQgZm9yIG9wdCAoKlR4T3B0aW9uKSwgdGhlIGZvbGxvd2luZyBkZWZhdWx0cyBhcmUgdXNlZDoKLy8gICZUeE9wdGlvbnN7Ci8vICAJVGltZW91dDogICA1ICogdGltZS5TZWNvbmQsCi8vICAJSXNvbGF0aW9uOiBzcWwuTGV2ZWxTZXJpYWxpemFibGUsCi8vICAJUmVhZE9ubHk6ICBmYWxzZSwKLy8gIH0KZnVuYyBFeGVjdXRlVHJhbnNhY3Rpb24oZGIgKnNxbC5EQiwgb3B0ICpUeE9wdGlvbnMsIGFjdGlvbnMgZnVuYygqc3FsLlR4KSBlcnJvcikgKGVyciBlcnJvcikgewoJLy8gUHJvdmlkZSBzYWZlIGRlZmF1bHRzIGluIGNhc2Ugbm9uZSB3ZXJlIGdpdmVuLgoJaWYgb3B0ID09IG5pbCB7CgkJb3B0ID0gJlR4T3B0aW9uc3sKCQkJVGltZW91dDogICA1ICogdGltZS5TZWNvbmQsCgkJCUlzb2xhdGlvbjogc3FsLkxldmVsU2VyaWFsaXphYmxlLAoJCQlSZWFkT25seTogIGZhbHNlLAoJCX0KCX0KCgkvLyBCdWlsZCB0aGUgY29udGV4dCB3aXRoIHRoZSBwcm92aWRlZCB0aW1lb3V0LgoJLy8gVGhpcyB3aWxsIGJlIHVzZWQgdG8gZGVmaW5lIHRoZSB0b3RhbCB0aW1lIHRoZSB0cmFuc2FjdGlvbiBtYXkgdGFrZSwKCS8vIHBhc3QgdGhpcyB0aW1lLCBpdCB3aWxsIGJlIGNhbmNlbGxlZCwgcm9sbGJhY2ssIHRoZW4gdGhyb3cgYW4gZXJyb3IuCgljdHgsIGNhbmNlbCA6PSBjb250ZXh0LldpdGhUaW1lb3V0KGNvbnRleHQuQmFja2dyb3VuZCgpLCBvcHQuVGltZW91dCkKCWRlZmVyIGNhbmNlbCgpCgoJdmFyIHR4ICpzcWwuVHgKCWlmIHR4LCBlcnIgPSBkYi5CZWdpblR4KGN0eCwgJnNxbC5UeE9wdGlvbnN7CgkJSXNvbGF0aW9uOiBvcHQuSXNvbGF0aW9uLAoJCVJlYWRPbmx5OiAgb3B0LlJlYWRPbmx5LAoJfSk7IGVyciAhPSBuaWwgewoJCXJldHVybiBlcnIKCX0KCglkZWZlciBmdW5jKCkgewoJCWlmIHIgOj0gcmVjb3ZlcigpOyByICE9IG5pbCB7CgkJCS8vIE9ubHkgbmVlZCB0byBsb2cgaGVyZSBiZWNhdXNlIHBhbmljIHdvbid0IHJlcG9ydCB3aGV0aGVyCgkJCS8vIHRoZSByb2xsYmFjayB3YXMgc3VjY2Vzc2Z1bCBvciBub3QuCgkJCWlmIHR4ZXJyIDo9IHR4LlJvbGxiYWNrKCk7IHR4ZXJyICE9IG5pbCB7CgkJCQlsb2cuUHJpbnRsbigiZGIgcm9sbGJhY2sgZXJyb3I6IiwgdHhlcnIpCgkJCX0KCgkJCWxvZy5QcmludGYoInJvbGxlZCBiYWNrIHRyYW5zYWN0aW9uIikKCQkJcGFuaWMocikKCQl9IGVsc2UgaWYgZXJyICE9IG5pbCB7CgkJCS8vIElmIHdlIHJ1biBpbnRvIGlzc3VlcyByb2xsaW5nIGJhY2ssIGtlZXAgdHJhY2sgb2YgdGhlIGVycm9yIHRoYXQKCQkJLy8gY2F1c2VkIHRoZSBpc3N1ZSBhbmQgcHJvdmlkZSBzb21lIGNvbnRleHQgb24gdGhlIHJvbGxiYWNrIGZhaWx1cmUuCgkJCWlmIHJlcnIgOj0gdHguUm9sbGJhY2soKTsgcmVyciAhPSBuaWwgewoJCQkJZXJyID0gZm10LkVycm9yZigiZGIgZXJyb3I6ICV2IHJvbGxiYWNrIGVycm9yOiAldiIsIGVyciwgcmVycikKCQkJfQoJCX0gZWxzZSB7CgkJCWlmIGNlcnIgOj0gdHguQ29tbWl0KCk7IGNlcnIgIT0gbmlsIHsKCQkJCWVyciA9IGZtdC5FcnJvcmYoImNvbW1pdCBlcnJvcjogJXYiLCBjZXJyKQoJCQl9CgkJfQoJfSgpCgoJZXJyID0gYWN0aW9ucyh0eCkKCXJldHVybiBlcnIKfQp7e2VuZH19Cg==\"") packr.PackJSONBytes("./tmpl", "x_helpers_test.html", "\"e3tkZWZpbmUgImhlbHBlcnN0ZXN0In19Ci8vK2J1aWxkICFoZWxwZXJzCgpwYWNrYWdlIHt7IC5QYWNrYWdlTmFtZSB9fQoKLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCnwgQ29kZSBnZW5lcmF0ZWQgYnkgbW9kZWxnZW4gfAp8ICAgICAgICBETyBOT1QgRURJVC4gICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCgppbXBvcnQgKAoJImRhdGFiYXNlL3NxbC9kcml2ZXIiCgkiZW5jb2RpbmcvanNvbiIKCSJyZWZsZWN0IgoJInRlc3RpbmciCgkidGltZSIKKQoKZnVuYyBUZXN0U3RydWN0RW1iZWRkaW5nKHQgKnRlc3RpbmcuVCkgewoJdGltIDo9IHRpbWUuRGF0ZSgyMDE3LCAxLCAxLCAwLCAwLCAwLCAwLCB0aW1lLlVUQykKCWV4cGVjdGVkIDo9IFtdYnl0ZShgeyJhIjoxMjMsImIiOnRydWUsImMiOjEyMy4xMjMsImQiOiJzdHJpbmciLCJlIjoiMjAxNy0wMS0wMVQwMDowMDowMFoiLCJmIjpbMSwyLDNdfWApCgl0eXBlIGVtYmVkIHN0cnVjdCB7CgkJQSBOdWxsSW50NjQgICBganNvbjoiYSxvbWl0ZW1wdHkiYAoJCUIgTnVsbEJvb2wgICAgYGpzb246ImIsb21pdGVtcHR5ImAKCQlDIE51bGxGbG9hdDY0IGBqc29uOiJjLG9taXRlbXB0eSJgCgkJRCBOdWxsU3RyaW5nICBganNvbjoiZCxvbWl0ZW1wdHkiYAoJCUUgTnVsbFRpbWUgICAgYGpzb246ImUsb21pdGVtcHR5ImAKCQlGIFJhd0pTT04gICAgIGBqc29uOiJmLG9taXRlbXB0eSJgCgl9CgllbSA6PSBlbWJlZHsKCQlBOiBOdWxsSW50NjR7VmFsaWQ6IHRydWUsIEludDY0OiAxMjN9LAoJCUI6IE51bGxCb29se1ZhbGlkOiB0cnVlLCBCb29sOiB0cnVlfSwKCQlDOiBOdWxsRmxvYXQ2NHtWYWxpZDogdHJ1ZSwgRmxvYXQ2NDogMTIzLjEyM30sCgkJRDogTnVsbFN0cmluZ3tWYWxpZDogdHJ1ZSwgU3RyaW5nOiAic3RyaW5nIn0sCgkJRTogTnVsbFRpbWV7VmFsaWQ6IHRydWUsIFRpbWU6IHRpbX0sCgkJRjogUmF3SlNPTihgWzEsMiwzXWApLAoJfQoJYiwgZXJyIDo9IGpzb24uTWFyc2hhbChlbSkKCWlmIGVyciAhPSBuaWwgewoJCXQuRmF0YWwoZXJyKQoJfQoJaWYgIXJlZmxlY3QuRGVlcEVxdWFsKGV4cGVjdGVkLCBiKSB7CgkJdC5GYXRhbCgibm90IHRoZSBzYW1lIEpTT04hIikKCX0KCWlmICEoc3RyaW5nKGIpID09IHN0cmluZyhleHBlY3RlZCkpIHsKCQl0LkZhdGFsKCJub3QgdGhlIHNhbWUhIikKCX0KCgl2YXIgZW0yIGVtYmVkCglpZiBlcnIgOj0ganNvbi5Vbm1hcnNoYWwoZXhwZWN0ZWQsICZlbTIpOyBlcnIgIT0gbmlsIHsKCQl0LkZhdGFsKGVycikKCX0KCWlmICFyZWZsZWN0LkRlZXBFcXVhbChlbTIsIGVtKSB7CgkJdC5GYXRhbCgibm90IGNvcnJlY3QiKQoJfQp9CgpmdW5jIFRlc3ROdWxsU3RyaW5nX1VubWFyc2hhbEpTT04odCAqdGVzdGluZy5UKSB7Cgl0ZXN0cyA6PSBbXXN0cnVjdCB7CgkJbmFtZSAgICBzdHJpbmcKCQluICAgICAgIE51bGxTdHJpbmcKCQlzb3VyY2UgIFtdYnl0ZQoJCXdhbnRFcnIgYm9vbAoJfXsKCQl7CgkJCW5hbWU6ICAgICJleHBsaWNpdCBudWxsIiwKCQkJc291cmNlOiAgW11ieXRlKGBudWxsYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgkJewoJCQluYW1lOiAgICAic3RyaW5nIG51bGwiLAoJCQlzb3VyY2U6ICBbXWJ5dGUoYCJudWxsImApLAoJCQl3YW50RXJyOiBmYWxzZSwgLy8gdGhpcyBvbmUgU0hPVUxEIGJlIHZhbGlkCgkJfSwKCQl7CgkJCW5hbWU6ICAgICJ2YWxpZCIsCgkJCXNvdXJjZTogIFtdYnl0ZShgImhlbGxvImApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogICAgImludmFsaWQiLAoJCQlzb3VyY2U6ICBbXWJ5dGUoYHsia2V5IjoidmFsdWUifWApLAoJCQl3YW50RXJyOiB0cnVlLAoJCX0sCgkJewoJCQluYW1lOiAgICAiZW1wdHkiLAoJCQlzb3VyY2U6ICBbXWJ5dGV7fSwKCQkJd2FudEVycjogdHJ1ZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlpZiBlcnIgOj0gdHQubi5Vbm1hcnNoYWxKU09OKHR0LnNvdXJjZSk7IChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsU3RyaW5nLlVubWFyc2hhbEpTT04oKSBlcnJvciA9ICV2LCB3YW50RXJyICV2IiwgZXJyLCB0dC53YW50RXJyKQoJCQl9CgkJfSkKCX0KfQoKZnVuYyBUZXN0TnVsbFN0cmluZ19WYWx1ZSh0ICp0ZXN0aW5nLlQpIHsKCXRlc3RzIDo9IFtdc3RydWN0IHsKCQluYW1lICAgIHN0cmluZwoJCW4gICAgICAgTnVsbFN0cmluZwoJCXdhbnQgICAgZHJpdmVyLlZhbHVlCgkJd2FudEVyciBib29sCgl9ewoJCXsKCQkJbmFtZTogInZhbGlkIiwKCQkJbjogTnVsbFN0cmluZ3sKCQkJCVZhbGlkOiAgdHJ1ZSwKCQkJCVN0cmluZzogImhlbGxvIiwKCQkJfSwKCQkJd2FudDogICAgZHJpdmVyLlZhbHVlKCJoZWxsbyIpLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogImludmFsaWQiLAoJCQluOiBOdWxsU3RyaW5newoJCQkJVmFsaWQ6IGZhbHNlLAoJCQl9LAoJCQl3YW50OiAgICBuaWwsCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWdvdCwgZXJyIDo9IHR0Lm4uVmFsdWUoKQoJCQlpZiAoZXJyICE9IG5pbCkgIT0gdHQud2FudEVyciB7CgkJCQl0LkVycm9yZigiTnVsbFN0cmluZy5WYWx1ZSgpIGVycm9yID0gJXYsIHdhbnRFcnIgJXYiLCBlcnIsIHR0LndhbnRFcnIpCgkJCQlyZXR1cm4KCQkJfQoJCQlpZiAhcmVmbGVjdC5EZWVwRXF1YWwoZ290LCB0dC53YW50KSB7CgkJCQl0LkVycm9yZigiTnVsbFN0cmluZy5WYWx1ZSgpID0gJXYsIHdhbnQgJXYiLCBnb3QsIHR0LndhbnQpCgkJCX0KCQl9KQoJfQp9CgpmdW5jIFRlc3ROdWxsU3RyaW5nX1NjYW4odCAqdGVzdGluZy5UKSB7Cgl0ZXN0cyA6PSBbXXN0cnVjdCB7CgkJbmFtZSAgICBzdHJpbmcKCQluICAgICAgICpOdWxsU3RyaW5nCgkJd2FudEVyciBib29sCgkJc3JjICAgICBpbnRlcmZhY2V7fQoJfXsKCQl7CgkJCW5hbWU6ICJ2YWxpZCIsCgkJCW46ICZOdWxsU3RyaW5newoJCQkJU3RyaW5nOiAiaGVsbG8iLAoJCQkJVmFsaWQ6ICB0cnVlLAoJCQl9LAoJCQlzcmM6ICAgICAiIiwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJuaWwgdmFsdWUiLAoJCQluOiAmTnVsbFN0cmluZ3sKCQkJCVN0cmluZzogImhlbGxvIiwKCQkJCVZhbGlkOiAgZmFsc2UsCgkJCX0sCgkJCXNyYzogICAgIG5pbCwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCX0KCWZvciBfLCB0dCA6PSByYW5nZSB0ZXN0cyB7CgkJdC5SdW4odHQubmFtZSwgZnVuYyh0ICp0ZXN0aW5nLlQpIHsKCQkJaWYgZXJyIDo9IHR0Lm4uU2Nhbih0dC5zcmMpOyAoZXJyICE9IG5pbCkgIT0gdHQud2FudEVyciB7CgkJCQl0LkVycm9yZigiTnVsbFN0cmluZy5TY2FuKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJfQoJCQlpZiAhdHQubi5WYWxpZCAmJiB0dC5zcmMgIT0gbmlsIHsKCQkJCXQuRXJyb3JmKCJzaG91bGQgcmV0dXJuIG51bGwiKQoJCQl9CgkJCWlmIHR0Lm4uVmFsaWQgJiYgdHQuc3JjICE9IHR0Lm4uU3RyaW5nIHsKCQkJCXQuRXJyb3JmKCJpbnZhbGlkIHZhbHVlIikKCQkJfQoJCX0pCgl9Cn0KCmZ1bmMgVGVzdE51bGxTdHJpbmdfTWFyc2hhbEpTT04odCAqdGVzdGluZy5UKSB7Cgl0ZXN0cyA6PSBbXXN0cnVjdCB7CgkJbmFtZSAgICBzdHJpbmcKCQluICAgICAgICpOdWxsU3RyaW5nCgkJd2FudCAgICBbXWJ5dGUKCQl3YW50RXJyIGJvb2wKCX17CgkJewoJCQluYW1lOiAidmFsaWQiLAoJCQluOiAmTnVsbFN0cmluZ3sKCQkJCVN0cmluZzogImhlbGxvIiwKCQkJCVZhbGlkOiAgdHJ1ZSwKCQkJfSwKCQkJd2FudDogICAgW11ieXRlKGAiaGVsbG8iYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgkJewoJCQluYW1lOiAidmFsaWQgbnVsbCIsCgkJCW46ICZOdWxsU3RyaW5newoJCQkJU3RyaW5nOiAiIiwKCQkJCVZhbGlkOiAgZmFsc2UsCgkJCX0sCgkJCXdhbnQ6ICAgIFtdYnl0ZShgbnVsbGApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogImludmFsaWQiLAoJCQluOiAmTnVsbFN0cmluZ3sKCQkJCVZhbGlkOiB0cnVlLAoJCQl9LAoJCQl3YW50OiAgICBbXWJ5dGUoYCIiYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWdvdCwgZXJyIDo9IHR0Lm4uTWFyc2hhbEpTT04oKQoJCQlpZiAoZXJyICE9IG5pbCkgIT0gdHQud2FudEVyciB7CgkJCQl0LkVycm9yZigiTnVsbFN0cmluZy5NYXJzaGFsSlNPTigpIGVycm9yID0gJXYsIHdhbnRFcnIgJXYiLCBlcnIsIHR0LndhbnRFcnIpCgkJCQlyZXR1cm4KCQkJfQoJCQlpZiAhcmVmbGVjdC5EZWVwRXF1YWwoZ290LCB0dC53YW50KSB7CgkJCQl0LkVycm9yZigiTnVsbFN0cmluZy5NYXJzaGFsSlNPTigpID0gJXYsIHdhbnQgJXYiLCBnb3QsIHR0LndhbnQpCgkJCX0KCQl9KQoJfQp9CgpmdW5jIFRlc3ROdWxsQm9vbF9Vbm1hcnNoYWxKU09OKHQgKnRlc3RpbmcuVCkgewoJdGVzdHMgOj0gW11zdHJ1Y3QgewoJCW5hbWUgICAgICAgICBzdHJpbmcKCQluICAgICAgICAgICAgTnVsbEJvb2wKCQlzb3VyY2UgICAgICAgW11ieXRlCgkJd2FudEVyciAgICAgIGJvb2wKCQl3YW50VmFsaWRpdHkgYm9vbAoJfXsKCQl7CgkJCW5hbWU6ICAgICAgICAgImV4cGxpY2l0IG51bGwiLAoJCQlzb3VyY2U6ICAgICAgIFtdYnl0ZShgbnVsbGApLAoJCQl3YW50RXJyOiAgICAgIGZhbHNlLAoJCQl3YW50VmFsaWRpdHk6IGZhbHNlLAoJCX0sCgkJewoJCQluYW1lOiAgICAgICAgICJ2YWxpZCIsCgkJCXNvdXJjZTogICAgICAgW11ieXRlKGBmYWxzZWApLAoJCQl3YW50RXJyOiAgICAgIGZhbHNlLAoJCQl3YW50VmFsaWRpdHk6IHRydWUsCgkJfSwKCQl7CgkJCW5hbWU6ICAgICAgICAgImludmFsaWQiLAoJCQlzb3VyY2U6ICAgICAgIFtdYnl0ZShgeyJrZXkiOiJ2YWx1ZSJ9YCksCgkJCXdhbnRFcnI6ICAgICAgdHJ1ZSwKCQkJd2FudFZhbGlkaXR5OiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogICAgICAgICAiZW1wdHkiLAoJCQlzb3VyY2U6ICAgICAgIFtdYnl0ZXt9LAoJCQl3YW50RXJyOiAgICAgIHRydWUsCgkJCXdhbnRWYWxpZGl0eTogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICAgICAgICAgImV4cGxpY2l0IG51bGwiLAoJCQlzb3VyY2U6ICAgICAgIFtdYnl0ZSgibnVsbCIpLAoJCQl3YW50RXJyOiAgICAgIGZhbHNlLAoJCQl3YW50VmFsaWRpdHk6IGZhbHNlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWlmIGVyciA6PSB0dC5uLlVubWFyc2hhbEpTT04odHQuc291cmNlKTsgKGVyciAhPSBuaWwpICE9IHR0LndhbnRFcnIgJiYgdHQubi5WYWxpZCA9PSB0dC53YW50VmFsaWRpdHkgewoJCQkJdC5FcnJvcmYoIk51bGxCb29sLlVubWFyc2hhbEpTT04oKSBlcnJvciA9ICV2LCB3YW50RXJyICV2IiwgZXJyLCB0dC53YW50RXJyKQoJCQl9CgkJfSkKCX0KfQoKZnVuYyBUZXN0TnVsbEJvb2xfVmFsdWUodCAqdGVzdGluZy5UKSB7Cgl0ZXN0cyA6PSBbXXN0cnVjdCB7CgkJbmFtZSAgICBzdHJpbmcKCQluICAgICAgIE51bGxCb29sCgkJd2FudCAgICBkcml2ZXIuVmFsdWUKCQl3YW50RXJyIGJvb2wKCX17CgkJewoJCQluYW1lOiAidmFsaWQiLAoJCQluOiBOdWxsQm9vbHsKCQkJCVZhbGlkOiB0cnVlLAoJCQkJQm9vbDogIHRydWUsCgkJCX0sCgkJCXdhbnQ6ICAgIGRyaXZlci5WYWx1ZSh0cnVlKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJpbnZhbGlkIiwKCQkJbjogTnVsbEJvb2x7CgkJCQlWYWxpZDogZmFsc2UsCgkJCX0sCgkJCXdhbnQ6ICAgIG5pbCwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCX0KCWZvciBfLCB0dCA6PSByYW5nZSB0ZXN0cyB7CgkJdC5SdW4odHQubmFtZSwgZnVuYyh0ICp0ZXN0aW5nLlQpIHsKCQkJZ290LCBlcnIgOj0gdHQubi5WYWx1ZSgpCgkJCWlmIChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsQm9vbC5WYWx1ZSgpIGVycm9yID0gJXYsIHdhbnRFcnIgJXYiLCBlcnIsIHR0LndhbnRFcnIpCgkJCQlyZXR1cm4KCQkJfQoJCQlpZiAhcmVmbGVjdC5EZWVwRXF1YWwoZ290LCB0dC53YW50KSB7CgkJCQl0LkVycm9yZigiTnVsbEJvb2wuVmFsdWUoKSA9ICV2LCB3YW50ICV2IiwgZ290LCB0dC53YW50KQoJCQl9CgkJfSkKCX0KfQoKZnVuYyBUZXN0TnVsbEJvb2xfU2Nhbih0ICp0ZXN0aW5nLlQpIHsKCXRlc3RzIDo9IFtdc3RydWN0IHsKCQluYW1lICAgIHN0cmluZwoJCW4gICAgICAgKk51bGxCb29sCgkJd2FudEVyciBib29sCgkJc3JjICAgICBpbnRlcmZhY2V7fQoJfXsKCQl7CgkJCW5hbWU6ICJ2YWxpZCIsCgkJCW46ICZOdWxsQm9vbHsKCQkJCUJvb2w6ICB0cnVlLAoJCQkJVmFsaWQ6IHRydWUsCgkJCX0sCgkJCXNyYzogICAgIHRydWUsCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgkJewoJCQluYW1lOiAibmlsIHZhbHVlIiwKCQkJbjogJk51bGxCb29sewoJCQkJQm9vbDogIHRydWUsCgkJCQlWYWxpZDogZmFsc2UsCgkJCX0sCgkJCXNyYzogICAgIGZhbHNlLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlpZiBlcnIgOj0gdHQubi5TY2FuKHR0LnNyYyk7IChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsQm9vbC5TY2FuKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJfQoJCQlpZiAhdHQubi5WYWxpZCAmJiB0dC5zcmMgIT0gbmlsIHsKCQkJCXQuRXJyb3JmKCJzaG91bGQgcmV0dXJuIG51bGwiKQoJCQl9CgkJCWlmIHR0Lm4uVmFsaWQgJiYgdHQuc3JjICE9IHR0Lm4uQm9vbCB7CgkJCQl0LkVycm9yZigiaW52YWxpZCB2YWx1ZSIpCgkJCX0KCQl9KQoJfQp9CgpmdW5jIFRlc3ROdWxsQm9vbF9NYXJzaGFsSlNPTih0ICp0ZXN0aW5nLlQpIHsKCXRlc3RzIDo9IFtdc3RydWN0IHsKCQluYW1lICAgIHN0cmluZwoJCW4gICAgICAgKk51bGxCb29sCgkJd2FudCAgICBbXWJ5dGUKCQl3YW50RXJyIGJvb2wKCX17CgkJewoJCQluYW1lOiAidmFsaWQiLAoJCQluOiAmTnVsbEJvb2x7CgkJCQlWYWxpZDogdHJ1ZSwKCQkJfSwKCQkJd2FudDogICAgW11ieXRlKGBmYWxzZWApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogInZhbGlkIG51bGwiLAoJCQluOiAmTnVsbEJvb2x7CgkJCQlWYWxpZDogZmFsc2UsCgkJCX0sCgkJCXdhbnQ6ICAgIFtdYnl0ZShgbnVsbGApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogImludmFsaWQiLAoJCQluOiAmTnVsbEJvb2x7CgkJCQlWYWxpZDogdHJ1ZSwKCQkJfSwKCQkJd2FudDogICAgW11ieXRlKGBmYWxzZWApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlnb3QsIGVyciA6PSB0dC5uLk1hcnNoYWxKU09OKCkKCQkJaWYgKGVyciAhPSBuaWwpICE9IHR0LndhbnRFcnIgewoJCQkJdC5FcnJvcmYoIk51bGxCb29sLk1hcnNoYWxKU09OKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJCXJldHVybgoJCQl9CgkJCWlmICFyZWZsZWN0LkRlZXBFcXVhbChnb3QsIHR0LndhbnQpIHsKCQkJCXQuRXJyb3JmKCJOdWxsQm9vbC5NYXJzaGFsSlNPTigpID0gJXYsIHdhbnQgJXYiLCBnb3QsIHR0LndhbnQpCgkJCX0KCQl9KQoJfQp9CgpmdW5jIFRlc3ROdWxsVGltZV9Vbm1hcnNoYWxKU09OKHQgKnRlc3RpbmcuVCkgewoJdGVzdHMgOj0gW11zdHJ1Y3QgewoJCW5hbWUgICAgc3RyaW5nCgkJbiAgICAgICBOdWxsVGltZQoJCXNvdXJjZSAgW11ieXRlCgkJd2FudEVyciBib29sCgl9ewoJCXsKCQkJbmFtZTogICAgInZhbGlkIiwKCQkJc291cmNlOiAgW11ieXRlKGAiMjAxNy0xMS0yNFQwMDowMDowMFoiYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgkJewoJCQluYW1lOiAgICAiaW52YWxpZCIsCgkJCXNvdXJjZTogIFtdYnl0ZShgeyJrZXkiOiJ2YWx1ZSJ9YCksCgkJCXdhbnRFcnI6IHRydWUsCgkJfSwKCQl7CgkJCW5hbWU6ICAgICJlbXB0eSIsCgkJCXNvdXJjZTogIFtdYnl0ZXt9LAoJCQl3YW50RXJyOiB0cnVlLAoJCX0sCgkJewoJCQluYW1lOiAgICAiZXhwbGljaXQgbnVsbCIsCgkJCXNvdXJjZTogIFtdYnl0ZShgbnVsbGApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlpZiBlcnIgOj0gdHQubi5Vbm1hcnNoYWxKU09OKHR0LnNvdXJjZSk7IChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsQm9vbC5Vbm1hcnNoYWxKU09OKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJfQoJCX0pCgl9Cn0KCmZ1bmMgVGVzdE51bGxUaW1lX1ZhbHVlKHQgKnRlc3RpbmcuVCkgewoJdGltIDo9IHRpbWUuTm93KCkKCXRlc3RzIDo9IFtdc3RydWN0IHsKCQluYW1lICAgIHN0cmluZwoJCW4gICAgICAgTnVsbFRpbWUKCQl3YW50ICAgIGRyaXZlci5WYWx1ZQoJCXdhbnRFcnIgYm9vbAoJfXsKCQl7CgkJCW5hbWU6ICJ2YWxpZCIsCgkJCW46IE51bGxUaW1lewoJCQkJVmFsaWQ6IHRydWUsCgkJCQlUaW1lOiAgdGltLAoJCQl9LAoJCQl3YW50OiAgICBkcml2ZXIuVmFsdWUodGltKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJpbnZhbGlkIiwKCQkJbjogTnVsbFRpbWV7CgkJCQlWYWxpZDogZmFsc2UsCgkJCX0sCgkJCXdhbnQ6ICAgIG5pbCwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCX0KCWZvciBfLCB0dCA6PSByYW5nZSB0ZXN0cyB7CgkJdC5SdW4odHQubmFtZSwgZnVuYyh0ICp0ZXN0aW5nLlQpIHsKCQkJZ290LCBlcnIgOj0gdHQubi5WYWx1ZSgpCgkJCWlmIChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsVGltZS5WYWx1ZSgpIGVycm9yID0gJXYsIHdhbnRFcnIgJXYiLCBlcnIsIHR0LndhbnRFcnIpCgkJCQlyZXR1cm4KCQkJfQoJCQlpZiAhcmVmbGVjdC5EZWVwRXF1YWwoZ290LCB0dC53YW50KSB7CgkJCQl0LkVycm9yZigiTnVsbFRpbWUuVmFsdWUoKSA9ICV2LCB3YW50ICV2IiwgZ290LCB0dC53YW50KQoJCQl9CgkJfSkKCX0KfQoKZnVuYyBUZXN0TnVsbFRpbWVfU2Nhbih0ICp0ZXN0aW5nLlQpIHsKCXRpbSA6PSB0aW1lLk5vdygpCgl0ZXN0cyA6PSBbXXN0cnVjdCB7CgkJbmFtZSAgICBzdHJpbmcKCQluICAgICAgICpOdWxsVGltZQoJCXdhbnRFcnIgYm9vbAoJCXNyYyAgICAgaW50ZXJmYWNle30KCX17CgkJewoJCQluYW1lOiAidmFsaWQiLAoJCQluOiAmTnVsbFRpbWV7CgkJCQlUaW1lOiAgdGltLAoJCQkJVmFsaWQ6IHRydWUsCgkJCX0sCgkJCXNyYzogICAgIHRpbSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJuaWwgdmFsdWUiLAoJCQluOiAmTnVsbFRpbWV7CgkJCQlUaW1lOiAgdGltLAoJCQkJVmFsaWQ6IGZhbHNlLAoJCQl9LAoJCQlzcmM6ICAgICB0aW1lLk5vdygpLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlpZiBlcnIgOj0gdHQubi5TY2FuKHR0LnNyYyk7IChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsVGltZS5TY2FuKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJfQoJCQlpZiAhdHQubi5WYWxpZCAmJiB0dC5zcmMgIT0gbmlsIHsKCQkJCXQuRXJyb3JmKCJzaG91bGQgcmV0dXJuIG51bGwiKQoJCQl9CgkJCWlmIHR0Lm4uVmFsaWQgJiYgdHQuc3JjICE9IHR0Lm4uVGltZSB7CgkJCQl0LkVycm9yZigiaW52YWxpZCB2YWx1ZSIpCgkJCX0KCQl9KQoJfQp9CgpmdW5jIFRlc3ROdWxsVGltZV9NYXJzaGFsSlNPTih0ICp0ZXN0aW5nLlQpIHsKCXRlc3RzIDo9IFtdc3RydWN0IHsKCQluYW1lICAgIHN0cmluZwoJCW4gICAgICAgKk51bGxUaW1lCgkJd2FudCAgICBbXWJ5dGUKCQl3YW50RXJyIGJvb2wKCX17CgkJewoJCQluYW1lOiAidmFsaWQiLAoJCQluOiAmTnVsbFRpbWV7CgkJCQlUaW1lOiAgdGltZS5EYXRlKDIwMTcsIDExLCAyNCwgMCwgMCwgMCwgMCwgdGltZS5VVEMpLAoJCQkJVmFsaWQ6IHRydWUsCgkJCX0sCgkJCXdhbnQ6ICAgIFtdYnl0ZShgIjIwMTctMTEtMjRUMDA6MDA6MDBaImApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogInZhbGlkIG51bGwiLAoJCQluOiAmTnVsbFRpbWV7CgkJCQlWYWxpZDogZmFsc2UsCgkJCX0sCgkJCXdhbnQ6ICAgIFtdYnl0ZShgbnVsbGApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogImludmFsaWQiLAoJCQluOiAmTnVsbFRpbWV7CgkJCQlWYWxpZDogdHJ1ZSwKCQkJfSwKCQkJd2FudDogICAgW11ieXRlKGAiMDAwMS0wMS0wMVQwMDowMDowMFoiYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWdvdCwgZXJyIDo9IHR0Lm4uTWFyc2hhbEpTT04oKQoJCQlpZiAoZXJyICE9IG5pbCkgIT0gdHQud2FudEVyciB7CgkJCQl0LkVycm9yZigiTnVsbFRpbWUuTWFyc2hhbEpTT04oKSBlcnJvciA9ICV2LCB3YW50RXJyICV2IiwgZXJyLCB0dC53YW50RXJyKQoJCQkJcmV0dXJuCgkJCX0KCQkJaWYgIXJlZmxlY3QuRGVlcEVxdWFsKGdvdCwgdHQud2FudCkgewoJCQkJdC5FcnJvcmYoIk51bGxUaW1lLk1hcnNoYWxKU09OKCkgPSAldiwgd2FudCAldiIsIGdvdCwgdHQud2FudCkKCQkJfQoJCX0pCgl9Cn0KCmZ1bmMgVGVzdE51bGxJbnQ2NF9Vbm1hcnNoYWxKU09OKHQgKnRlc3RpbmcuVCkgewoJdGVzdHMgOj0gW11zdHJ1Y3QgewoJCW5hbWUgICAgc3RyaW5nCgkJbiAgICAgICBOdWxsSW50NjQKCQlzb3VyY2UgIFtdYnl0ZQoJCXdhbnRFcnIgYm9vbAoJfXsKCQl7CgkJCW5hbWU6ICAgICJ2YWxpZCIsCgkJCXNvdXJjZTogIFtdYnl0ZShgMTIzYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgkJewoJCQluYW1lOiAgICAiaW52YWxpZCIsCgkJCXNvdXJjZTogIFtdYnl0ZShgeyJrZXkiOiJ2YWx1ZSJ9YCksCgkJCXdhbnRFcnI6IHRydWUsCgkJfSwKCQl7CgkJCW5hbWU6ICAgICJlbXB0eSIsCgkJCXNvdXJjZTogIFtdYnl0ZXt9LAoJCQl3YW50RXJyOiB0cnVlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWlmIGVyciA6PSB0dC5uLlVubWFyc2hhbEpTT04odHQuc291cmNlKTsgKGVyciAhPSBuaWwpICE9IHR0LndhbnRFcnIgewoJCQkJdC5FcnJvcmYoIk51bGxJbnQ2NC5Vbm1hcnNoYWxKU09OKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJfQoJCX0pCgl9Cn0KCmZ1bmMgVGVzdE51bGxJbnQ2NF9WYWx1ZSh0ICp0ZXN0aW5nLlQpIHsKCXRlc3RzIDo9IFtdc3RydWN0IHsKCQluYW1lICAgIHN0cmluZwoJCW4gICAgICAgTnVsbEludDY0CgkJd2FudCAgICBkcml2ZXIuVmFsdWUKCQl3YW50RXJyIGJvb2wKCX17CgkJewoJCQluYW1lOiAidmFsaWQiLAoJCQluOiBOdWxsSW50NjR7CgkJCQlWYWxpZDogdHJ1ZSwKCQkJCUludDY0OiAxMjMsCgkJCX0sCgkJCXdhbnQ6ICAgIGRyaXZlci5WYWx1ZShpbnQ2NCgxMjMpKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJpbnZhbGlkIiwKCQkJbjogTnVsbEludDY0ewoJCQkJVmFsaWQ6IGZhbHNlLAoJCQl9LAoJCQl3YW50OiAgICBuaWwsCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWdvdCwgZXJyIDo9IHR0Lm4uVmFsdWUoKQoJCQlpZiAoZXJyICE9IG5pbCkgIT0gdHQud2FudEVyciB7CgkJCQl0LkVycm9yZigiTnVsbEludDY0LlZhbHVlKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJCXJldHVybgoJCQl9CgkJCWlmICFyZWZsZWN0LkRlZXBFcXVhbChnb3QsIHR0LndhbnQpIHsKCQkJCXQuRXJyb3JmKCJOdWxsSW50NjQuVmFsdWUoKSA9ICV2LCB3YW50ICV2IiwgZ290LCB0dC53YW50KQoJCQl9CgkJfSkKCX0KfQoKZnVuYyBUZXN0TnVsbEludDY0X1NjYW4odCAqdGVzdGluZy5UKSB7Cgl0ZXN0cyA6PSBbXXN0cnVjdCB7CgkJbmFtZSAgICBzdHJpbmcKCQluICAgICAgICpOdWxsSW50NjQKCQl3YW50RXJyIGJvb2wKCQlzcmMgICAgIGludGVyZmFjZXt9Cgl9ewoJCXsKCQkJbmFtZTogInZhbGlkIiwKCQkJbjogJk51bGxJbnQ2NHsKCQkJCUludDY0OiAxMjMsCgkJCQlWYWxpZDogdHJ1ZSwKCQkJfSwKCQkJc3JjOiAgICAgaW50NjQoMTIzKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJuaWwgdmFsdWUiLAoJCQluOiAmTnVsbEludDY0ewoJCQkJVmFsaWQ6IGZhbHNlLAoJCQl9LAoJCQlzcmM6ICAgICBpbnQ2NCgxMjMpLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlpZiBlcnIgOj0gdHQubi5TY2FuKHR0LnNyYyk7IChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsSW50NjQuU2NhbigpIGVycm9yID0gJXYsIHdhbnRFcnIgJXYiLCBlcnIsIHR0LndhbnRFcnIpCgkJCX0KCQkJaWYgIXR0Lm4uVmFsaWQgJiYgdHQuc3JjICE9IG5pbCB7CgkJCQl0LkVycm9yZigic2hvdWxkIHJldHVybiBudWxsIikKCQkJfQoJCQlpZiB0dC5uLlZhbGlkICYmIHR0LnNyYyAhPSB0dC5uLkludDY0IHsKCQkJCXQuRXJyb3JmKCJpbnZhbGlkIHZhbHVlIikKCQkJfQoJCX0pCgl9Cn0KCmZ1bmMgVGVzdE51bGxJbnQ2NF9NYXJzaGFsSlNPTih0ICp0ZXN0aW5nLlQpIHsKCXRlc3RzIDo9IFtdc3RydWN0IHsKCQluYW1lICAgIHN0cmluZwoJCW4gICAgICAgKk51bGxJbnQ2NAoJCXdhbnQgICAgW11ieXRlCgkJd2FudEVyciBib29sCgl9ewoJCXsKCQkJbmFtZTogInZhbGlkIiwKCQkJbjogJk51bGxJbnQ2NHsKCQkJCUludDY0OiAxMjMsCgkJCQlWYWxpZDogdHJ1ZSwKCQkJfSwKCQkJd2FudDogICAgW11ieXRlKGAxMjNgKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJ2YWxpZCBudWxsIiwKCQkJbjogJk51bGxJbnQ2NHsKCQkJCVZhbGlkOiBmYWxzZSwKCQkJfSwKCQkJd2FudDogICAgW11ieXRlKGBudWxsYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgkJewoJCQluYW1lOiAiaW52YWxpZCIsCgkJCW46ICZOdWxsSW50NjR7CgkJCQlWYWxpZDogdHJ1ZSwKCQkJfSwKCQkJd2FudDogICAgW11ieXRlKGAwYCksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWdvdCwgZXJyIDo9IHR0Lm4uTWFyc2hhbEpTT04oKQoJCQlpZiAoZXJyICE9IG5pbCkgIT0gdHQud2FudEVyciB7CgkJCQl0LkVycm9yZigiTnVsbEludDY0Lk1hcnNoYWxKU09OKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJCXJldHVybgoJCQl9CgkJCWlmICFyZWZsZWN0LkRlZXBFcXVhbChnb3QsIHR0LndhbnQpIHsKCQkJCXQuRXJyb3JmKCJOdWxsSW50NjQuTWFyc2hhbEpTT04oKSA9ICV2LCB3YW50ICV2IiwgZ290LCB0dC53YW50KQoJCQl9CgkJfSkKCX0KfQpmdW5jIFRlc3ROdWxsRmxvYXQ2NF9Vbm1hcnNoYWxKU09OKHQgKnRlc3RpbmcuVCkgewoJdGVzdHMgOj0gW11zdHJ1Y3QgewoJCW5hbWUgICAgc3RyaW5nCgkJbiAgICAgICBOdWxsRmxvYXQ2NAoJCXNvdXJjZSAgW11ieXRlCgkJd2FudEVyciBib29sCgl9ewoJCXsKCQkJbmFtZTogICAgImV4cGxpY2l0IG51bGwiLAoJCQlzb3VyY2U6ICBbXWJ5dGUoYG51bGxgKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICAgICJ2YWxpZCIsCgkJCXNvdXJjZTogIFtdYnl0ZShgMTIzLjEyM2ApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogICAgImludmFsaWQiLAoJCQlzb3VyY2U6ICBbXWJ5dGUoYHsia2V5IjoidmFsdWUifWApLAoJCQl3YW50RXJyOiB0cnVlLAoJCX0sCgkJewoJCQluYW1lOiAgICAiZW1wdHkiLAoJCQlzb3VyY2U6ICBbXWJ5dGV7fSwKCQkJd2FudEVycjogdHJ1ZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlpZiBlcnIgOj0gdHQubi5Vbm1hcnNoYWxKU09OKHR0LnNvdXJjZSk7IChlcnIgIT0gbmlsKSAhPSB0dC53YW50RXJyIHsKCQkJCXQuRXJyb3JmKCJOdWxsRmxvYXQ2NC5Vbm1hcnNoYWxKU09OKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJfQoJCX0pCgl9Cn0KCmZ1bmMgVGVzdE51bGxGbG9hdDY0X1ZhbHVlKHQgKnRlc3RpbmcuVCkgewoJdGVzdHMgOj0gW11zdHJ1Y3QgewoJCW5hbWUgICAgc3RyaW5nCgkJbiAgICAgICBOdWxsRmxvYXQ2NAoJCXdhbnQgICAgZHJpdmVyLlZhbHVlCgkJd2FudEVyciBib29sCgl9ewoJCXsKCQkJbmFtZTogInZhbGlkIiwKCQkJbjogTnVsbEZsb2F0NjR7CgkJCQlWYWxpZDogICB0cnVlLAoJCQkJRmxvYXQ2NDogMTIzLjEyMywKCQkJfSwKCQkJd2FudDogICAgZHJpdmVyLlZhbHVlKGZsb2F0NjQoMTIzLjEyMykpLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJCXsKCQkJbmFtZTogImludmFsaWQiLAoJCQluOiBOdWxsRmxvYXQ2NHsKCQkJCVZhbGlkOiBmYWxzZSwKCQkJfSwKCQkJd2FudDogICAgbmlsLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlnb3QsIGVyciA6PSB0dC5uLlZhbHVlKCkKCQkJaWYgKGVyciAhPSBuaWwpICE9IHR0LndhbnRFcnIgewoJCQkJdC5FcnJvcmYoIk51bGxGbG9hdDY0LlZhbHVlKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJCXJldHVybgoJCQl9CgkJCWlmICFyZWZsZWN0LkRlZXBFcXVhbChnb3QsIHR0LndhbnQpIHsKCQkJCXQuRXJyb3JmKCJOdWxsRmxvYXQ2NC5WYWx1ZSgpID0gJXYsIHdhbnQgJXYiLCBnb3QsIHR0LndhbnQpCgkJCX0KCQl9KQoJfQp9CgpmdW5jIFRlc3ROdWxsRmxvYXQ2NF9TY2FuKHQgKnRlc3RpbmcuVCkgewoJdGVzdHMgOj0gW11zdHJ1Y3QgewoJCW5hbWUgICAgc3RyaW5nCgkJbiAgICAgICAqTnVsbEZsb2F0NjQKCQl3YW50RXJyIGJvb2wKCQlzcmMgICAgIGludGVyZmFjZXt9Cgl9ewoJCXsKCQkJbmFtZTogInZhbGlkIiwKCQkJbjogJk51bGxGbG9hdDY0ewoJCQkJRmxvYXQ2NDogMTIzLjEyMywKCQkJCVZhbGlkOiAgIHRydWUsCgkJCX0sCgkJCXNyYzogICAgIGZsb2F0NjQoMTIzKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJuaWwgdmFsdWUiLAoJCQluOiAmTnVsbEZsb2F0NjR7CgkJCQlWYWxpZDogZmFsc2UsCgkJCX0sCgkJCXNyYzogICAgIGZsb2F0NjQoMTIzLjEyMyksCgkJCXdhbnRFcnI6IGZhbHNlLAoJCX0sCgl9Cglmb3IgXywgdHQgOj0gcmFuZ2UgdGVzdHMgewoJCXQuUnVuKHR0Lm5hbWUsIGZ1bmModCAqdGVzdGluZy5UKSB7CgkJCWlmIGVyciA6PSB0dC5uLlNjYW4odHQuc3JjKTsgKGVyciAhPSBuaWwpICE9IHR0LndhbnRFcnIgewoJCQkJdC5FcnJvcmYoIk51bGxGbG9hdDY0LlNjYW4oKSBlcnJvciA9ICV2LCB3YW50RXJyICV2IiwgZXJyLCB0dC53YW50RXJyKQoJCQl9CgkJCWlmICF0dC5uLlZhbGlkICYmIHR0LnNyYyAhPSBuaWwgewoJCQkJdC5FcnJvcmYoInNob3VsZCByZXR1cm4gbnVsbCIpCgkJCX0KCQkJaWYgdHQubi5WYWxpZCAmJiB0dC5zcmMgIT0gdHQubi5GbG9hdDY0IHsKCQkJCXQuRXJyb3JmKCJpbnZhbGlkIHZhbHVlIikKCQkJfQoJCX0pCgl9Cn0KCmZ1bmMgVGVzdE51bGxGbG9hdDY0X01hcnNoYWxKU09OKHQgKnRlc3RpbmcuVCkgewoJdGVzdHMgOj0gW11zdHJ1Y3QgewoJCW5hbWUgICAgc3RyaW5nCgkJbiAgICAgICAqTnVsbEZsb2F0NjQKCQl3YW50ICAgIFtdYnl0ZQoJCXdhbnRFcnIgYm9vbAoJfXsKCQl7CgkJCW5hbWU6ICJ2YWxpZCIsCgkJCW46ICZOdWxsRmxvYXQ2NHsKCQkJCUZsb2F0NjQ6IDEyMy4xMjMsCgkJCQlWYWxpZDogICB0cnVlLAoJCQl9LAoJCQl3YW50OiAgICBbXWJ5dGUoYDEyMy4xMjNgKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJ2YWxpZCBudWxsIiwKCQkJbjogJk51bGxGbG9hdDY0ewoJCQkJVmFsaWQ6IGZhbHNlLAoJCQl9LAoJCQl3YW50OiAgICBbXWJ5dGUoYG51bGxgKSwKCQkJd2FudEVycjogZmFsc2UsCgkJfSwKCQl7CgkJCW5hbWU6ICJpbnZhbGlkIiwKCQkJbjogJk51bGxGbG9hdDY0ewoJCQkJVmFsaWQ6IHRydWUsCgkJCX0sCgkJCXdhbnQ6ICAgIFtdYnl0ZShgMGApLAoJCQl3YW50RXJyOiBmYWxzZSwKCQl9LAoJfQoJZm9yIF8sIHR0IDo9IHJhbmdlIHRlc3RzIHsKCQl0LlJ1bih0dC5uYW1lLCBmdW5jKHQgKnRlc3RpbmcuVCkgewoJCQlnb3QsIGVyciA6PSB0dC5uLk1hcnNoYWxKU09OKCkKCQkJaWYgKGVyciAhPSBuaWwpICE9IHR0LndhbnRFcnIgewoJCQkJdC5FcnJvcmYoIk51bGxGbG9hdDY0Lk1hcnNoYWxKU09OKCkgZXJyb3IgPSAldiwgd2FudEVyciAldiIsIGVyciwgdHQud2FudEVycikKCQkJCXJldHVybgoJCQl9CgkJCWlmICFyZWZsZWN0LkRlZXBFcXVhbChnb3QsIHR0LndhbnQpIHsKCQkJCXQuRXJyb3JmKCJOdWxsRmxvYXQ2NC5NYXJzaGFsSlNPTigpID0gJXYsIHdhbnQgJXYiLCBnb3QsIHR0LndhbnQpCgkJCX0KCQl9KQoJfQp9CgpmdW5jIFRlc3RUb051bGxCb29sKHQgKnRlc3RpbmcuVCkgewoJYiA6PSB0cnVlCgliYiA6PSBUb051bGxCb29sKCZiKQoJaWYgIWJiLlZhbGlkIHsKCQl0LkVycm9yZigiZXhwZWN0ZWQgdmFsaWQsIGdvdCAldiIsIGJiLlZhbGlkKQoJfQoJaWYgIWJiLkJvb2wgewoJCXQuRXJyb3JmKCJleHBlY3RlZCB0cnVlLCBnb3QgJXYiLCBiYi5Cb29sKQoJfQoKCXZhciBiMiAqYm9vbAoJYmIyIDo9IFRvTnVsbEJvb2woYjIpCglpZiBiYjIuVmFsaWQgewoJCXQuRXJyb3JmKCJleHBlY3RlZCBub3QgdmFsaWQsIGdvdCAldiIsIGJiMi5WYWxpZCkKCX0KCWlmIGJiMi5Cb29sIHsKCQl0LkVycm9yZigiZXhwZWN0ZWQgZmFsc2UsIGdvdCAldiIsIGJiMi5Cb29sKQoJfQp9CmZ1bmMgVGVzdFRvTnVsbEludDY0KHQgKnRlc3RpbmcuVCkgewoJYiA6PSBpbnQ2NCgxMjMpCgliYiA6PSBUb051bGxJbnQ2NCgmYikKCWlmICFiYi5WYWxpZCB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIHZhbGlkLCBnb3QgJXYiLCBiYi5WYWxpZCkKCX0KCWlmIGJiLkludDY0ICE9IDEyMyB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIDEyMywgZ290ICV2IiwgYmIuSW50NjQpCgl9CgoJdmFyIGIyICppbnQ2NAoJYmIyIDo9IFRvTnVsbEludDY0KGIyKQoJaWYgYmIyLlZhbGlkIHsKCQl0LkVycm9yZigiZXhwZWN0ZWQgbm90IHZhbGlkLCBnb3QgJXYiLCBiYjIuVmFsaWQpCgl9CglpZiBiYjIuSW50NjQgIT0gMCB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIDAsIGdvdCAldiIsIGJiMi5JbnQ2NCkKCX0KfQoKZnVuYyBUZXN0VG9OdWxsRmxvYXQ2NCh0ICp0ZXN0aW5nLlQpIHsKCWIgOj0gZmxvYXQ2NCgxMjMuMTIzKQoJYmIgOj0gVG9OdWxsRmxvYXQ2NCgmYikKCWlmICFiYi5WYWxpZCB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIHZhbGlkLCBnb3QgJXYiLCBiYi5WYWxpZCkKCX0KCWlmIGJiLkZsb2F0NjQgIT0gMTIzLjEyMyB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIDEyMy4xMjMsIGdvdCAldiIsIGJiLkZsb2F0NjQpCgl9CgoJdmFyIGIyICpmbG9hdDY0CgliYjIgOj0gVG9OdWxsRmxvYXQ2NChiMikKCWlmIGJiMi5WYWxpZCB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIG5vdCB2YWxpZCwgZ290ICV2IiwgYmIyLlZhbGlkKQoJfQoJaWYgYmIyLkZsb2F0NjQgIT0gMCB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIDAsIGdvdCAldiIsIGJiMi5GbG9hdDY0KQoJfQp9CmZ1bmMgVGVzdFRvTnVsbFN0cmluZyh0ICp0ZXN0aW5nLlQpIHsKCWIgOj0gInF3ZSIKCWJiIDo9IFRvTnVsbFN0cmluZygmYikKCWlmICFiYi5WYWxpZCB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIHZhbGlkLCBnb3QgJXYiLCBiYi5WYWxpZCkKCX0KCWlmIGJiLlN0cmluZyAhPSAicXdlIiB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIHF3ZSwgZ290ICV2IiwgYmIuU3RyaW5nKQoJfQoKCXZhciBiMiAqc3RyaW5nCgliYjIgOj0gVG9OdWxsU3RyaW5nKGIyKQoJaWYgYmIyLlZhbGlkIHsKCQl0LkVycm9yZigiZXhwZWN0ZWQgbm90IHZhbGlkLCBnb3QgJXYiLCBiYjIuVmFsaWQpCgl9CglpZiBiYjIuU3RyaW5nICE9ICIiIHsKCQl0LkVycm9yZigiZXhwZWN0ZWQgPGVtcHR5IHN0cmluZz4sIGdvdCAldiIsIGJiMi5TdHJpbmcpCgl9Cn0KZnVuYyBUZXN0VG9OdWxsVGltZSh0ICp0ZXN0aW5nLlQpIHsKCXRpbSA6PSB0aW1lLk5vdygpCgliYiA6PSBUb051bGxUaW1lKHRpbSkKCWlmICFiYi5WYWxpZCB7CgkJdC5FcnJvcmYoImV4cGVjdGVkIHZhbGlkLCBnb3QgJXYiLCBiYi5WYWxpZCkKCX0KCWlmIGJiLlRpbWUgIT0gdGltIHsKCQl0LkVycm9yZigiZXhwZWN0ZWQgJXYsIGdvdCAldiIsIHRpbSwgYmIuVGltZSkKCX0KCgl0aW0gPSB0aW1lLlRpbWV7fQoJYmIgPSBUb051bGxUaW1lKHRpbSkKCWlmIGJiLlZhbGlkIHsKCQl0LkVycm9yZigiZXhwZWN0ZWQgaW52YWxpZCwgZ290ICV2IiwgYmIuVmFsaWQpCgl9CglpZiBiYi5UaW1lICE9IHRpbSB7CgkJdC5FcnJvcmYoImV4cGVjdGVkICV2LCBnb3QgJXYiLCB0aW0sIGJiLlRpbWUpCgl9Cn0KCmZ1bmMgVGVzdFJhd0pTT05fTWFyc2hhbEpTT04odCAqdGVzdGluZy5UKSB7CgljYXNlcyA6PSBbXXN0cnVjdCB7CgkJbmFtZSBzdHJpbmcKCQlkYXRhIFtdYnl0ZQoJCWV4cCAgc3RyaW5nCgl9ewoJCXsKCQkJbmFtZTogImVtcHR5IGRhdGEiLAoJCQlkYXRhOiBbXWJ5dGV7fSwKCQkJZXhwOiAgIm51bGwiLAoJCX0sCgl9CgoJZm9yIF8sIGMgOj0gcmFuZ2UgY2FzZXMgewoJCXQuUnVuKGMubmFtZSwgZnVuYyh0ICp0ZXN0aW5nLlQpIHsKCQkJcmogOj0gUmF3SlNPTihjLmRhdGEpCgkJCWIsIGVyciA6PSByai5NYXJzaGFsSlNPTigpCgkJCWlmIGVyciAhPSBuaWwgewoJCQkJdC5GYXRhbGYoInVuZXhwZWN0ZWQgZXJyb3I6ICV2IiwgZXJyKQoJCQl9CgkJCWlmIHN0cmluZyhiKSAhPSBjLmV4cCB7CgkJCQl0LkZhdGFsZigiXG5leHA6ICVxXG5nb3Q6ICVxIiwgYy5leHAsIHN0cmluZyhiKSkKCQkJfQoJCX0pCgl9Cn0Ke3tlbmR9fQo=\"") - } +} diff --git a/generate.go b/generate.go index 9922bfb..5317e4c 100644 --- a/generate.go +++ b/generate.go @@ -104,6 +104,8 @@ func getTables() (tables map[string]string) { return tables } +// GetOrderFromComment reads the modelgen:1 type comments and returns +// the integer part on the right func GetOrderFromComment(comment string) (order int) { if !strings.HasPrefix(comment, "modelgen") { return @@ -120,11 +122,17 @@ func GetOrderFromComment(comment string) (order int) { return } +// backtick is needed is the user picked a table name +// which conflicts with a builtin keyword, example "order" +func backtick(s string) string { return "`" + s + "`" } + +// ToStructs takes an 'EXPLAIN' statement and transforms it's output +// into structs. func ToStructs(tables map[string]string) []tmpl.TmplStruct { var explained = make(map[string][]sqltypes.Explain) for table := range tables { var expl []sqltypes.Explain - rows, err := database.Query("EXPLAIN " + table) + rows, err := database.Query("EXPLAIN " + backtick(table)) if err != nil { log.Fatal(err) } diff --git a/init.sql b/init.sql index 79147d5..4089f44 100644 --- a/init.sql +++ b/init.sql @@ -2,6 +2,15 @@ CREATE DATABASE `modelgen_tests`; USE `modelgen_tests`; +-- order is a builtin, tests should pass despite this +DROP TABLE IF EXISTS `order`; + +-- only one field should not break despite the special cases. +CREATE TABLE `order` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + DROP TABLE IF EXISTS `common_cases`; CREATE TABLE `common_cases` ( diff --git a/tmpl/model.html b/tmpl/model.html index 299dd08..3c9332e 100644 --- a/tmpl/model.html +++ b/tmpl/model.html @@ -29,7 +29,7 @@ // Insert a new {{.Model.Name}} row in the {{.Model.TableName}} table func ({{.Receiver}} *{{.Model.Name}}) Insert(qu Queryer) (lastInsertID int64, err error) { const stmt = "INSERT INTO {{.Model.TableName}} ({{.Model.Fields | insert_fields}}) VALUES ({{.Model.Fields | insert_values}})" - res, err := qu.Exec(stmt, {{ . | insert_args }}) + res, err := qu.Exec(stmt{{ . | insert_args }}) if err != nil { return 0, err } @@ -39,7 +39,7 @@ // Update an existing {{.Model.Name}} row in the {{.Model.TableName}} table. func ({{.Receiver}} *{{.Model.Name}}) Update(qu Queryer, id int64) (int64, error) { const stmt = "UPDATE {{.Model.TableName}} SET {{ . | update_values }} WHERE id = ?" - result, err := qu.Exec(stmt, {{ . | update_args }} , id) + result, err := qu.Exec(stmt, {{ . | update_args }} id) if err != nil { return 0, err } diff --git a/tmpl/tmpl.go b/tmpl/tmpl.go index 1f5f739..8d9475c 100644 --- a/tmpl/tmpl.go +++ b/tmpl/tmpl.go @@ -7,16 +7,16 @@ import ( ) var FuncMap = template.FuncMap{ - "insert_fields": GetInsertFields, - "insert_values": GetInsertValues, - "insert_args": GetInsertArgs, - "scan_fields": GetScanFields, - "update_args": GetUpdateArgs, - "update_values": GetUpdateValues, - "upsert_fields": GetUpsertFields, - "upsert_values": GetUpsertValues, + "insert_fields": GetInsertFields, + "insert_values": GetInsertValues, + "insert_args": GetInsertArgs, + "scan_fields": GetScanFields, + "update_args": GetUpdateArgs, + "update_values": GetUpdateValues, + "upsert_fields": GetUpsertFields, + "upsert_values": GetUpsertValues, "upsert_on_duplicate": GetUpsertOnDuplicate, - "upsert_args": GetUpsertArgs, + "upsert_args": GetUpsertArgs, } func GetInsertFields(fields []TmplField) string { @@ -55,7 +55,10 @@ func GetInsertArgs(m StructTmplData) string { } parts = append(parts, fmt.Sprintf("%s.%s", m.Receiver, fl.Name)) } - return strings.Join(parts, ", ") + if len(parts) > 0 { + return ", " + strings.Join(parts, ", ") + } + return "" } func GetScanFields(m StructTmplData) template.HTML { @@ -75,7 +78,10 @@ func GetUpdateArgs(m StructTmplData) template.HTML { } parts = append(parts, fmt.Sprintf("%s.%s", m.Receiver, fl.Name)) } - return template.HTML(strings.Join(parts, ", ")) + if len(parts) > 0 { + return template.HTML(strings.Join(parts, ", ") + ", ") + } + return "" } func GetUpdateValues(m StructTmplData) string { @@ -142,4 +148,4 @@ func GetUpsertArgs(m StructTmplData) string { parts = append(parts, fmt.Sprintf("%s.%s", m.Receiver, fl.Name)) } return strings.Join(parts, ", ") -} \ No newline at end of file +}