From 806bb6cc992e3fcbddd9326ef0e70e55db5e853d Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:22:12 -0400 Subject: [PATCH 1/4] feat: binary coverage Retrieve coverage from instrumented `manifestd` --- .github/workflows/codecov.yml | 2 +- Makefile | 31 +++++++-- README.md | 9 +++ chains.yaml | 11 +++- go.work.sum | 12 ++++ interchaintest/go.mod | 8 +-- interchaintest/go.sum | 20 +++--- interchaintest/helpers/action_builder.go | 4 +- interchaintest/helpers/block.go | 2 +- interchaintest/ibc_test.go | 18 ++++++ interchaintest/mainfest_test.go | 9 ++- interchaintest/poa_test.go | 81 ++++++++++++++++++++++-- interchaintest/setup.go | 53 +++++++++++++++- interchaintest/tokenfactory_test.go | 11 ++++ 14 files changed, 237 insertions(+), 34 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index a0b3dbf..188a621 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -22,7 +22,7 @@ jobs: wget -c https://github.com/strangelove-ventures/heighliner/releases/download/v1.5.4/heighliner_1.5.4_linux_amd64.tar.gz -O - | tar -xz heighliner mv heighliner /usr/local/bin - name: Make local image - run: make local-image + run: make local-image-cov - name: Run coverage run: make coverage - name: Upload coverage to Codecov diff --git a/Makefile b/Makefile index 146eaab..569809f 100644 --- a/Makefile +++ b/Makefile @@ -85,6 +85,12 @@ install: @echo "--> installing manifestd" @go install $(BUILD_FLAGS) -mod=readonly ./cmd/manifestd +install-cover: + @echo "--> ensure dependencies have not been modified" + @go mod verify + @echo "--> installing manifestd instrumented for coverage" + @go install $(BUILD_FLAGS) -cover -covermode=atomic -mod=readonly -coverpkg=github.com/liftedinit/manifest-ledger/... ./cmd/manifestd + init: ./scripts/init.sh @@ -135,7 +141,14 @@ else heighliner build -c manifest --local -f ./chains.yaml endif -.PHONY: get-heighliner local-image +local-image-cov: +ifeq (,$(shell which heighliner)) + echo 'heighliner' binary not found. Consider running `make get-heighliner` +else + heighliner build -c manifest-cov --local -f ./chains.yaml +endif + +.PHONY: get-heighliner local-image local-image-cov ################# ### Test ### @@ -156,17 +169,23 @@ test-integration: ################# coverage: ## Run coverage report + @echo "--> Creating GOCOVERDIR" + @mkdir -p /tmp/manifest-ledger-coverage + @echo "--> Cleaning up coverage files, if any" + @rm -rf /tmp/manifest-ledger-coverage/* @echo "--> Running coverage" - @go test -race -cpu=$$(nproc) -covermode=atomic -coverprofile=coverage.out $$(go list ./...) ./interchaintest/... -coverpkg=github.com/liftedinit/manifest-ledger/... > /dev/null 2>&1 - @echo "--> Running coverage filter" + @go test -race -covermode=atomic -v -cpu=$$(nproc) -cover $$(go list ./...) ./interchaintest/... -coverpkg=github.com/liftedinit/manifest-ledger/... -args -test.gocoverdir="/tmp/manifest-ledger-coverage" > /dev/null 2>&1 + @echo "--> Converting binary coverage report to text format" + @go tool covdata textfmt -i=/tmp/manifest-ledger-coverage -o coverage.out + @echo "--> Filtering coverage report" @./scripts/filter-coverage.sh - @echo "--> Running coverage report" + @echo "--> Generating coverage report" @go tool cover -func=coverage-filtered.out - @echo "--> Running coverage html" + @echo "--> Generating HTML coverage report" @go tool cover -html=coverage-filtered.out -o coverage.html @echo "--> Coverage report available at coverage.html" @echo "--> Cleaning up coverage files" - @rm coverage.out + @rm coverage.out /tmp/manifest-ledger-coverage/* @echo "--> Running coverage complete" .PHONY: coverage diff --git a/README.md b/README.md index ce3309b..a56d971 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,15 @@ make ictest-manifest make ictest-ibc ``` +## Coverage + +To generate a coverage report for the modules run: + +```bash +make local-image-cov +make coverage +```` + ## Helper There are scripts for testing, installing, and initializing. Use this section to help you navigate the various scripts and their use cases. diff --git a/chains.yaml b/chains.yaml index a73d18e..a70756a 100644 --- a/chains.yaml +++ b/chains.yaml @@ -8,4 +8,13 @@ - /go/bin/manifestd build-env: - LEDGER_ENABLED=false - - BUILD_TAGS=muslc \ No newline at end of file + - BUILD_TAGS=muslc + +- name: manifest-cov + dockerfile: cosmos + build-target: make install-cover + binaries: + - /go/bin/manifestd + build-env: + - LEDGER_ENABLED=false + - BUILD_TAGS=muslc diff --git a/go.work.sum b/go.work.sum index d786355..09421dc 100644 --- a/go.work.sum +++ b/go.work.sum @@ -622,18 +622,24 @@ github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNu github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk= +github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY= github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= +github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 h1:GY1+t5Dr9OKADM64SYnQjw/w99HMYvQ0A8/JoUkxVmc= github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/fmorency/interchaintest/v8 v8.0.0-20240416193951-ace087670ed4 h1:T4jvaehxysfMDQYT5aNPfU2Bp4+zl5R0MKDTRAnbupA= +github.com/fmorency/interchaintest/v8 v8.0.0-20240416193951-ace087670ed4/go.mod h1:B1TjQjU1te0ek05LQGjDwEu1NwWpfmC3+eAEDtouY+0= github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= @@ -654,6 +660,8 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdk github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= +github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= +github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= @@ -886,6 +894,8 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -1118,6 +1128,8 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= diff --git a/interchaintest/go.mod b/interchaintest/go.mod index 92efe53..a0ae74c 100644 --- a/interchaintest/go.mod +++ b/interchaintest/go.mod @@ -15,12 +15,13 @@ require ( cosmossdk.io/math v1.3.0 github.com/cosmos/cosmos-sdk v0.50.5 github.com/cosmos/ibc-go/v8 v8.2.0 + github.com/docker/docker v24.0.9+incompatible github.com/liftedinit/manifest-ledger v0.0.0-00000000000000-000000000000 - github.com/strangelove-ventures/interchaintest/v8 v8.1.0 + github.com/strangelove-ventures/interchaintest/v8 v8.2.0 github.com/strangelove-ventures/poa v0.50.0 github.com/strangelove-ventures/tokenfactory v0.50.0 github.com/stretchr/testify v1.9.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 ) require ( @@ -92,13 +93,12 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.9+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/emicklei/dot v1.6.1 // indirect - github.com/ethereum/go-ethereum v1.13.8 // indirect + github.com/ethereum/go-ethereum v1.13.14 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect diff --git a/interchaintest/go.sum b/interchaintest/go.sum index b2acc89..acb8923 100644 --- a/interchaintest/go.sum +++ b/interchaintest/go.sum @@ -463,8 +463,8 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= -github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= -github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/ethereum/go-ethereum v1.13.14 h1:EwiY3FZP94derMCIam1iW4HFVrSgIcpsu0HwTQtm6CQ= +github.com/ethereum/go-ethereum v1.13.14/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= @@ -510,8 +510,8 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= @@ -1055,8 +1055,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/strangelove-ventures/interchaintest/v8 v8.1.0 h1:+VOGGR2sEP2gLvx0ojRONt8oKMHk+2mjVdOmarsdbvc= -github.com/strangelove-ventures/interchaintest/v8 v8.1.0/go.mod h1:kXw3vLQdEEcvyJ3ZindGPigpHgIdwrywNsQKkARb+qM= +github.com/strangelove-ventures/interchaintest/v8 v8.2.0 h1:EZXPvZXL1y/kvh9XI04A2stL+2UMvykhNUv28euRnL8= +github.com/strangelove-ventures/interchaintest/v8 v8.2.0/go.mod h1:pupV0YN3A56/u9kHj9U1F8MdDUEolBIn05F0W1q/0oI= github.com/strangelove-ventures/poa v0.50.0 h1:ZLDVv4ZK+FeKyAcJ9ahS6SgAOch8wvGr/txAKWQmcvg= github.com/strangelove-ventures/poa v0.50.0/go.mod h1:LcmorSGWRyn/M5hch7dAW7l0aYL+VSw28uzdsjdOduc= github.com/strangelove-ventures/tokenfactory v0.50.0 h1:r5ja0CDrACAeCdP/LMhfdXZQFK6YEXE7yfNZ1+jZyg4= @@ -1155,8 +1155,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -1166,8 +1166,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/interchaintest/helpers/action_builder.go b/interchaintest/helpers/action_builder.go index 98d1220..9805eff 100644 --- a/interchaintest/helpers/action_builder.go +++ b/interchaintest/helpers/action_builder.go @@ -27,7 +27,7 @@ func ExecuteExec(ctx context.Context, chain *cosmos.CosmosChain, cmd []string, i command = append(command, extraFlags...) fmt.Println(command) - stdout, _, err := chain.Exec(ctx, command, nil) + stdout, _, err := chain.Exec(ctx, command, chain.Config().Env) if err != nil { fmt.Println(err) } @@ -44,7 +44,7 @@ func ExecuteTransaction(ctx context.Context, chain *cosmos.CosmosChain, cmd []st var stdout []byte var res sdk.TxResponse - stdout, _, err = chain.Exec(ctx, cmd, nil) + stdout, _, err = chain.Exec(ctx, cmd, chain.Config().Env) if err != nil { return sdk.TxResponse{}, err } diff --git a/interchaintest/helpers/block.go b/interchaintest/helpers/block.go index 1924922..362a0fd 100644 --- a/interchaintest/helpers/block.go +++ b/interchaintest/helpers/block.go @@ -8,7 +8,7 @@ import ( "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" ) -func GetBlockData(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, height uint64) BlockData { +func GetBlockData(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, height int64) BlockData { var res BlockData ExecuteQuery(ctx, chain, []string{"query", "block", "--type=height", fmt.Sprintf("%d", height)}, &res) return res diff --git a/interchaintest/ibc_test.go b/interchaintest/ibc_test.go index b23ebae..a285930 100644 --- a/interchaintest/ibc_test.go +++ b/interchaintest/ibc_test.go @@ -2,6 +2,8 @@ package interchaintest import ( "context" + "fmt" + "path" "testing" "cosmossdk.io/math" @@ -20,11 +22,22 @@ func TestIBC(t *testing.T) { t.Parallel() ctx := context.Background() + // Same as ChainNode.HomeDir() but we need it before the chain is created + // The node volume is always mounted at /var/cosmos-chain/[chain-name] + // This is a hackish way to get the coverage files from the ephemeral containers cfgA := LocalChainConfig cfgA.ChainID = "manifest-9" + internalGoCoverDirA := path.Join("/var/cosmos-chain", cfgA.ChainID) + cfgA.Env = []string{ + fmt.Sprintf("GOCOVERDIR=%s", internalGoCoverDirA), + } cfgB := LocalChainConfig cfgB.ChainID = "manifest-10" + internalGoCoverDirB := path.Join("/var/cosmos-chain", cfgB.ChainID) + cfgB.Env = []string{ + fmt.Sprintf("GOCOVERDIR=%s", internalGoCoverDirB), + } cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t, zaptest.Level(zapcore.DebugLevel)), []*interchaintest.ChainSpec{ { @@ -133,4 +146,9 @@ func TestIBC(t *testing.T) { osmosUserBalNew, err := manifestB.GetBalance(ctx, manifestBUser.FormattedAddress(), dstIbcDenom) require.NoError(t, err) require.True(t, osmosUserBalNew.Equal(amountToSend)) + + t.Cleanup(func() { + CopyCoverageFromContainer(ctx, t, client, manifestA.GetNode().ContainerID(), manifestA.HomeDir()) + CopyCoverageFromContainer(ctx, t, client, manifestB.GetNode().ContainerID(), manifestB.HomeDir()) + }) } diff --git a/interchaintest/mainfest_test.go b/interchaintest/mainfest_test.go index 3f09faa..e8881c8 100644 --- a/interchaintest/mainfest_test.go +++ b/interchaintest/mainfest_test.go @@ -3,6 +3,7 @@ package interchaintest import ( "context" "fmt" + "path" "testing" sdkmath "cosmossdk.io/math" @@ -22,9 +23,15 @@ func TestManifestModule(t *testing.T) { t.Parallel() ctx := context.Background() + + // Same as ChainNode.HomeDir() but we need it before the chain is created + // The node volume is always mounted at /var/cosmos-chain/[chain-name] + // This is a hackish way to get the coverage files from the ephemeral containers cfgA := LocalChainConfig + internalGoCoverDir := path.Join("/var/cosmos-chain", cfgA.ChainID) cfgA.Env = []string{ fmt.Sprintf("POA_ADMIN_ADDRESS=%s", accAddr), + fmt.Sprintf("GOCOVERDIR=%s", internalGoCoverDir), } cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t, zaptest.Level(zapcore.DebugLevel)), []*interchaintest.ChainSpec{ @@ -61,7 +68,6 @@ func TestManifestModule(t *testing.T) { // Chains appChain := chains[0].(*cosmos.CosmosChain) - poaAdmin, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "acc0", accMnemonic, DefaultGenesisAmt, appChain) if err != nil { t.Fatal(err) @@ -150,6 +156,7 @@ func TestManifestModule(t *testing.T) { }) t.Cleanup(func() { + CopyCoverageFromContainer(ctx, t, client, appChain.GetNode().ContainerID(), appChain.HomeDir()) _ = ic.Close() }) } diff --git a/interchaintest/poa_test.go b/interchaintest/poa_test.go index 17b5bbd..a4dfe6f 100644 --- a/interchaintest/poa_test.go +++ b/interchaintest/poa_test.go @@ -2,15 +2,19 @@ package interchaintest import ( "context" + "encoding/json" + "fmt" + "path" + "strings" "testing" + sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/strangelove-ventures/interchaintest/v8" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v8/ibc" + "github.com/strangelove-ventures/interchaintest/v8/testutil" "github.com/strangelove-ventures/poa" - - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" "github.com/liftedinit/manifest-ledger/interchaintest/helpers" @@ -29,12 +33,26 @@ func TestPOA(t *testing.T) { t.Skip("skipping in short mode") } + // Same as ChainNode.HomeDir() but we need it before the chain is created + // The node volume is always mounted at /var/cosmos-chain/[chain-name] + // This is a hackish way to get the coverage files from the ephemeral containers + name := "poa" + internalGoCoverDir := path.Join("/var/cosmos-chain", name) + + cfgA := LocalChainConfig + cfgA.Env = []string{ + fmt.Sprintf("GOCOVERDIR=%s", internalGoCoverDir), + } + // setup base chain - chains := interchaintest.CreateChainWithConfig(t, numVals, numNodes, "poa", "", LocalChainConfig) + chains := interchaintest.CreateChainWithConfig(t, numVals, numNodes, name, "", cfgA) chain := chains[0].(*cosmos.CosmosChain) enableBlockDB := false - ctx, _, _, _ := interchaintest.BuildInitialChain(t, chains, enableBlockDB) + ctx, _, client, _ := interchaintest.BuildInitialChain(t, chains, enableBlockDB) + + // Make sure the chain's HomeDir and the GOCOVERDIR are the same + require.Equal(t, internalGoCoverDir, chain.GetNode().HomeDir()) // setup accounts acc0, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "acc0", accMnemonic, DefaultGenesisAmt, chain) @@ -64,6 +82,50 @@ func TestPOA(t *testing.T) { // === Test Cases === testStakingDisabled(t, ctx, chain, validators, acc0, acc1) testPowerErrors(t, ctx, chain, validators, incorrectUser, acc0) + + t.Cleanup(func() { + // Copy coverage files from the container + CopyCoverageFromContainer(ctx, t, client, chain.GetNode().ContainerID(), chain.HomeDir()) + }) +} + +// createAuthzJSON generates a JSON file for an authorization message. +// This is a copy of interchaintest/chain/cosmos/module_authz.go#createAuthzJSON with the addition of the chain environment variables to the Exec call +func createAuthzJSON(ctx context.Context, chain *cosmos.CosmosChain, filePath string, genMsgCmd []string) error { + if !strings.Contains(strings.Join(genMsgCmd, " "), "--generate-only") { + genMsgCmd = append(genMsgCmd, "--generate-only") + } + + res, resErr, err := chain.GetNode().Exec(ctx, genMsgCmd, chain.Config().Env) + if resErr != nil { + return fmt.Errorf("failed to generate msg: %s", resErr) + } + if err != nil { + return err + } + + return chain.GetNode().WriteFile(ctx, res, filePath) +} + +// ExecTx executes a transaction, waits for 2 blocks if successful, then returns the tx hash. +// This is a copy of interchaintest/chain/cosmos/chain_node.go#ExecTx with the addition of the chain environment variables to the Exec call +func ExecTx(ctx context.Context, chain *cosmos.CosmosChain, keyName string, command ...string) (string, error) { + stdout, _, err := chain.GetNode().Exec(ctx, chain.GetNode().TxCommand(keyName, command...), chain.Config().Env) + if err != nil { + return "", err + } + output := cosmos.CosmosTx{} + err = json.Unmarshal([]byte(stdout), &output) + if err != nil { + return "", err + } + if output.Code != 0 { + return output.TxHash, fmt.Errorf("transaction failed with code %d: %s", output.Code, output.RawLog) + } + if err := testutil.WaitForBlocks(ctx, 2, chain.GetNode()); err != nil { + return "", err + } + return output.TxHash, nil } func testStakingDisabled(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, validators []string, acc0, acc1 ibc.Wallet) { @@ -86,9 +148,14 @@ func testStakingDisabled(t *testing.T, ctx context.Context, chain *cosmos.Cosmos nestedCmd := helpers.TxCommandBuilder(ctx, chain, nested, granter.FormattedAddress()) // Execute nested message via a wrapped Exec - _, err = chain.GetNode().AuthzExec(ctx, grantee, nestedCmd) + // Workaround AuthzExec which doesn't propagate the environment variables to the Exec call + fileName := "authz.json" + err = createAuthzJSON(ctx, chain, fileName, nestedCmd) + require.NoError(t, err) + + _, err = ExecTx(ctx, chain, grantee.KeyName(), []string{"authz", "exec", path.Join(chain.GetNode().HomeDir(), fileName)}...) require.Error(t, err) - require.Contains(t, err.Error(), poa.ErrStakingActionNotAllowed.Error()) + require.ErrorContains(t, err, poa.ErrStakingActionNotAllowed.Error()) } func testPowerErrors(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, validators []string, incorrectUser ibc.Wallet, admin ibc.Wallet) { @@ -106,7 +173,7 @@ func testPowerErrors(t *testing.T, ctx context.Context, chain *cosmos.CosmosChai t.Run("fail: set-power message below minimum power requirement (self bond)", func(t *testing.T) { res, err = helpers.POASetPower(t, ctx, chain, admin, validators[0], 1) require.Error(t, err) // cli validate error - require.Contains(t, err.Error(), poa.ErrPowerBelowMinimum.Error()) + require.ErrorContains(t, err, poa.ErrPowerBelowMinimum.Error()) }) } diff --git a/interchaintest/setup.go b/interchaintest/setup.go index 84fc3aa..926258e 100644 --- a/interchaintest/setup.go +++ b/interchaintest/setup.go @@ -1,8 +1,20 @@ package interchaintest import ( + "archive/tar" + "bytes" + "context" + "io" + "os" + "path" + "path/filepath" + "strings" + "testing" + + "github.com/docker/docker/client" poatypes "github.com/strangelove-ventures/poa" tokenfactorytypes "github.com/strangelove-ventures/tokenfactory/x/tokenfactory/types" + "github.com/stretchr/testify/require" types "github.com/liftedinit/manifest-ledger/x/manifest/types" @@ -13,6 +25,10 @@ import ( sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" ) +const ( + ExternalGoCoverDir = "/tmp/manifest-ledger-coverage" +) + var ( votingPeriod = "15s" maxDepositPeriod = "10s" @@ -56,7 +72,7 @@ var ( ChainID: "manifest-2", Images: []ibc.DockerImage{ { - Repository: "manifest", + Repository: "manifest-cov", Version: "local", UidGid: "1025:1025", }, @@ -83,3 +99,38 @@ func AppEncoding() *sdktestutil.TestEncodingConfig { return &enc } + +func CopyCoverageFromContainer(ctx context.Context, t *testing.T, client *client.Client, containerId string, internalGoCoverDir string) { + r, _, err := client.CopyFromContainer(ctx, containerId, internalGoCoverDir) + require.NoError(t, err) + defer r.Close() + + tr := tar.NewReader(r) + for { + hdr, err := tr.Next() + if err == io.EOF { + break // End of archive + } + require.NoError(t, err) + + var fileBuff bytes.Buffer + _, err = io.Copy(&fileBuff, tr) + require.NoError(t, err) + + name := hdr.Name + extractedFileName := path.Base(name) + + //Only extract coverage files + if !strings.HasPrefix(extractedFileName, "cov") { + continue + } + isDirectory := extractedFileName == "" + if isDirectory { + continue + } + + filePath := filepath.Join(ExternalGoCoverDir, extractedFileName) + err = os.WriteFile(filePath, fileBuff.Bytes(), os.ModePerm) + require.NoError(t, err) + } +} diff --git a/interchaintest/tokenfactory_test.go b/interchaintest/tokenfactory_test.go index 3e03582..15cac6d 100644 --- a/interchaintest/tokenfactory_test.go +++ b/interchaintest/tokenfactory_test.go @@ -2,6 +2,8 @@ package interchaintest import ( "context" + "fmt" + "path" "testing" "github.com/strangelove-ventures/interchaintest/v8" @@ -16,7 +18,15 @@ func TestTokenFactory(t *testing.T) { t.Parallel() ctx := context.Background() + + // Same as ChainNode.HomeDir() but we need it before the chain is created + // The node volume is always mounted at /var/cosmos-chain/[chain-name] + // This is a hackish way to get the coverage files from the ephemeral containers cfgA := LocalChainConfig + internalGoCoverDir := path.Join("/var/cosmos-chain", cfgA.ChainID) + cfgA.Env = []string{ + fmt.Sprintf("GOCOVERDIR=%s", internalGoCoverDir), + } cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t, zaptest.Level(zapcore.DebugLevel)), []*interchaintest.ChainSpec{ { @@ -128,6 +138,7 @@ func TestTokenFactory(t *testing.T) { } t.Cleanup(func() { + CopyCoverageFromContainer(ctx, t, client, appChain.GetNode().ContainerID(), appChain.HomeDir()) _ = ic.Close() }) } From 3cf4d3240698f3868b130d836b6fd55d49669b49 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:48:03 -0400 Subject: [PATCH 2/4] ci: bump codecov-action --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 188a621..28f0866 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -26,7 +26,7 @@ jobs: - name: Run coverage run: make coverage - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4-beta + uses: codecov/codecov-action@v4.3.0 with: file: coverage-filtered.out env: From 83198593b95b8aac6cd95613df8fd938e503e292 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:58:49 -0400 Subject: [PATCH 3/4] ci: fix e2e --- .github/workflows/e2e.yml | 4 +++- Dockerfile | 3 ++- Makefile | 10 +++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 09048e5..8c8df43 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -43,8 +43,10 @@ jobs: uses: docker/build-push-action@v5 with: context: . - tags: manifest:local + tags: manifest-cov:local outputs: type=docker,dest=${{ env.TAR_PATH }} + build-args: | + BUILD_CMD=build-cover - name: Upload artifact uses: actions/upload-artifact@v3 diff --git a/Dockerfile b/Dockerfile index 3a479c6..79953a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ FROM golang:1.22-alpine AS go-builder +ARG BUILD_CMD=build SHELL ["/bin/sh", "-ecuxo", "pipefail"] @@ -21,7 +22,7 @@ COPY . /code # force it to use static lib (from above) not standard libgo_cosmwasm.so file # then log output of file /code/bin/manifestd # then ensure static linking -RUN LEDGER_ENABLED=false BUILD_TAGS=muslc LINK_STATICALLY=true make build \ +RUN LEDGER_ENABLED=false BUILD_TAGS=muslc LINK_STATICALLY=true make $BUILD_CMD \ && file /code/build/manifestd \ && echo "Ensuring binary is statically linked ..." \ && (file /code/build/manifestd | grep "statically linked") diff --git a/Makefile b/Makefile index 569809f..321f917 100644 --- a/Makefile +++ b/Makefile @@ -102,10 +102,18 @@ else go build -mod=readonly $(BUILD_FLAGS) -o $(BUILD_DIR)/manifestd ./cmd/manifestd endif +build-cover: +ifeq ($(OS),Windows_NT) + $(error demo server not supported) + exit 1 +else + go build -mod=readonly $(BUILD_FLAGS) -cover -covermode=atomic -coverpkg=github.com/liftedinit/manifest-ledger/... -o $(BUILD_DIR)/manifestd ./cmd/manifestd +endif + build-vendored: go build -mod=vendor $(BUILD_FLAGS) -o $(BUILD_DIR)/manifestd ./cmd/manifestd -.PHONY: all build build-linux install init lint build-vendored +.PHONY: all build build-linux install init lint build-vendored build-cover ############################################################################### ### INTERCHAINTEST (ictest) ### From 974cce332b76155b4e1db2226f45d8f395a89230 Mon Sep 17 00:00:00 2001 From: "Felix C. Morency" <1102868+fmorency@users.noreply.github.com> Date: Thu, 18 Apr 2024 12:56:26 -0400 Subject: [PATCH 4/4] fix: create external gocoverdir --- interchaintest/setup.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interchaintest/setup.go b/interchaintest/setup.go index 926258e..07d20e4 100644 --- a/interchaintest/setup.go +++ b/interchaintest/setup.go @@ -105,6 +105,9 @@ func CopyCoverageFromContainer(ctx context.Context, t *testing.T, client *client require.NoError(t, err) defer r.Close() + err = os.MkdirAll(ExternalGoCoverDir, os.ModePerm) + require.NoError(t, err) + tr := tar.NewReader(r) for { hdr, err := tr.Next()