diff --git a/go.mod b/go.mod index ba2337294..fce1b984e 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,10 @@ require ( github.com/briandowns/spinner v1.20.0 github.com/disintegration/imaging v1.6.2 github.com/hashicorp/go-multierror v1.1.1 + github.com/obalunenko/getenv v1.1.0 github.com/obalunenko/logger v0.5.1 github.com/obalunenko/version v1.1.0 + github.com/olegfedoseev/image-diff v0.0.0-20171116094004-897a4e73dfd6 github.com/ory/dockertest/v3 v3.9.1 github.com/schollz/progressbar/v3 v3.12.2 github.com/spf13/viper v1.14.0 diff --git a/go.sum b/go.sum index 1d42912b2..f0e239829 100644 --- a/go.sum +++ b/go.sum @@ -238,10 +238,14 @@ github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXy github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/obalunenko/getenv v1.1.0 h1:vdaHNGjM0eahS+pXbld6enRNA74HEg+eYyiqgXja5GQ= +github.com/obalunenko/getenv v1.1.0/go.mod h1:rQSU30CHN52CamPdfTjUF4dk0oaoTo03kjxw2Yx3s2Y= github.com/obalunenko/logger v0.5.1 h1:49DIEwy4sBvRzM/OtD/m7zITi5L3S5DtSYZ/WoUrnno= github.com/obalunenko/logger v0.5.1/go.mod h1:/GnmNcmEV7tAL9StHrs3nDkXAK+TEvChoNY+YYRZww4= github.com/obalunenko/version v1.1.0 h1:yVua7OHnK3+MJpendeMmAlfzVmq7R1h8MO3Ufz7HEec= github.com/obalunenko/version v1.1.0/go.mod h1:Or267aCQxNcAtgOeWA7yOe/RqJS4XDaMfcFwk3ohbOg= +github.com/olegfedoseev/image-diff v0.0.0-20171116094004-897a4e73dfd6 h1:a/kynVgbdXJQDq3WWTgwL0bHyg4hu4/oIK9UB+Ugvfo= +github.com/olegfedoseev/image-diff v0.0.0-20171116094004-897a4e73dfd6/go.mod h1:OgMVaRcJ1TgmPHB/MF2YaHOzRxmw6vVG/DquoMhkCiY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= diff --git a/internal/media/ops_test.go b/internal/media/ops_test.go index 7e11b020e..ee7d9e15c 100644 --- a/internal/media/ops_test.go +++ b/internal/media/ops_test.go @@ -2,12 +2,15 @@ package media import ( "bytes" - "crypto/sha256" + "fmt" "io" "os" "path/filepath" + "strings" "testing" + "github.com/obalunenko/getenv" + diff "github.com/olegfedoseev/image-diff" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -17,6 +20,10 @@ type file struct { } func Test_addBorders(t *testing.T) { + if getenv.BoolOrDefault("CI", false) { + t.Skip("Doesn't work on CI") + } + type file struct { path string } @@ -119,7 +126,7 @@ func Test_addBorders(t *testing.T) { want := getReaderFromPath(t, tt.want.path) - diff(t, want, got) + diffImageReaders(t, want, got) }) } } @@ -133,18 +140,45 @@ func getReaderFromPath(tb testing.TB, path string) io.Reader { return bytes.NewReader(content) } -func diff(tb testing.TB, want, actual io.Reader) { +func diffImageReaders(tb testing.TB, want, actual io.Reader) { tb.Helper() - h1, h2 := sha256.New(), sha256.New() + wantimg, err := decode(want) + require.NoError(tb, err) - _, err := io.Copy(h1, want) + actimg, err := decode(actual) require.NoError(tb, err) - _, err = io.Copy(h2, actual) + var eq bool + + d, percent, err := diff.CompareImages(wantimg, actimg) require.NoError(tb, err) - assert.True(tb, bytes.Equal(h1.Sum(nil), h2.Sum(nil))) + if percent > 0.0 { + name := strings.ReplaceAll(fmt.Sprintf("%s_diff.jpg", tb.Name()), "/", "_") + + f, err := os.Create(filepath.Join("testdata", name)) + require.NoError(tb, err) + + tb.Cleanup(func() { + require.NoError(tb, f.Close()) + }) + + r, err := encode(d) + require.NoError(tb, err) + + buf := new(bytes.Buffer) + + _, err = buf.ReadFrom(r) + require.NoError(tb, err) + + _, err = f.Write(buf.Bytes()) + require.NoError(tb, err) + } else { + eq = true + } + + assert.True(tb, eq) } func Test_getFileContentType(t *testing.T) { diff --git a/internal/media/testdata/1440x960_heic.jpg b/internal/media/testdata/1440x960_heic.jpg deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/github.com/obalunenko/getenv/.gitattributes b/vendor/github.com/obalunenko/getenv/.gitattributes new file mode 100644 index 000000000..51452ff67 --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/.gitattributes @@ -0,0 +1,4 @@ +linguist-language=Go +*.go -text diff=golang +*.sh linguist-vendored +Makefile linguist-vendored diff --git a/vendor/github.com/obalunenko/getenv/.gitignore b/vendor/github.com/obalunenko/getenv/.gitignore new file mode 100644 index 000000000..cf6be1490 --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/.gitignore @@ -0,0 +1,22 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +bin/ +*.tape +dist/ +coverage/ +.DS_Store +tests-report.json \ No newline at end of file diff --git a/vendor/github.com/obalunenko/getenv/.golangci.pipe.yml b/vendor/github.com/obalunenko/getenv/.golangci.pipe.yml new file mode 100644 index 000000000..e115771e7 --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/.golangci.pipe.yml @@ -0,0 +1,126 @@ +linters: + disable-all: true + enable: + - errcheck + - gofmt + - revive + - goimports + +linters-settings: + errcheck: + check-type-assertions: true + check-blank: true + gofmt: + simplify: true + goimports: + local-prefixes: github.com/obalunenko/getenv/ + revive: + # see https://github.com/mgechev/revive#available-rules for details. + ignore-generated-header: true + severity: warning + rules: + - name: indent-error-flow + severity: warning + - name: exported + severity: warning + - name: defer + severity: warning + arguments: [ [ "call-chain", "loop", "method-call", "recover", "return" ] ] + +issues: + exclude-use-default: false + exclude: + # for "public interface + private struct implementation" cases only! + - exported func * returns unexported type *, which can be annoying to use + - should have a package comment, unless it's in another file for this package + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - gocyclo + - funlen + - dupl + - gosec + - path: internal/input/ + linters: + - gocyclo + - funlen + - godot + - godox + - dupl + - gofmt + - gci + - gofumpt + - goimports + - gosimple + - path: internal/puzzles/constants.go + linters: + - revive + + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing + # large codebase. It's not practical to fix all existing issues at the moment + # of integration: much better don't allow issues in new code. + # Default is false. + new: true + + # Fix found issues (if it's supported by the linter) + fix: false + + severity: + # Default value is empty string. + # Set the default severity for issues. If severity rules are defined and the issues + # do not match or no severity is provided to the rule this will be the default + # severity applied. Severities should match the supported severity names of the + # selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity + # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + default-severity: error + + # The default value is false. + # If set to true severity-rules regular expressions become case sensitive. + case-sensitive: false + + # Default value is empty list. + # When a list of severity rules are provided, severity information will be added to lint + # issues. Severity rules have the same filtering capability as exclude rules except you + # are allowed to specify one matcher per severity rule. + # Only affects out formats that support setting severity information. + rules: + - linters: + - dupl + severity: warning + +run: + issues-exit-code: 1 + tests: true + skip-dirs: + - vendor/ + skip-files: + - \.pb\.go$ + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions + # default is "colored-line-number" + format: github-actions + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true + + # make issues output unique by line, default is true + uniq-by-line: true + + # add a prefix to the output file references; default is no prefix + path-prefix: "" + + # sorts results by: filepath, line and column + sort-results: true + + diff --git a/vendor/github.com/obalunenko/getenv/.golangci.yml b/vendor/github.com/obalunenko/getenv/.golangci.yml new file mode 100644 index 000000000..0471ca09c --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/.golangci.yml @@ -0,0 +1,208 @@ +linters-settings: + depguard: + list-type: blacklist + packages: + # logging is allowed only by logutils.Log, logrus + # is allowed to use only in logutils package + - github.com/sirupsen/logrus + packages-with-error-message: + - github.com/sirupsen/logrus: "logging is allowed only by github.com/obalunenko/logger" + dupl: + threshold: 100 + funlen: + lines: 100 + statements: 50 + gci: + local-prefixes: github.com/obalunenko/getenv + goconst: + min-len: 2 + min-occurrences: 2 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + disabled-checks: + - dupImport # https://github.com/go-critic/go-critic/issues/845 + - ifElseChain + - hugeParam + - octalLiteral + - wrapperFunc + - sloppyReassign + gocyclo: + min-complexity: 15 + goimports: + local-prefixes: github.com/obalunenko/getenv + gomnd: + settings: + mnd: + # don't include the "operation" and "assign" + checks: [ argument,case,condition,return ] + govet: + check-shadowing: true + lll: + line-length: 140 + misspell: + locale: US + nolintlint: + allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) + allow-unused: false # report any unused nolint directives + require-explanation: false # don't require an explanation for nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - depguard + - dogsled + - dupl + - errcheck + - exportloopref + - exhaustive + - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + - gomnd + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - noctx + - nolintlint + - rowserrcheck + - staticcheck + - structcheck + - stylecheck + - typecheck + - unconvert + - unparam + - unused + - varcheck + - whitespace + - revive + - wsl + + # don't enable: + # - asciicheck + # - scopelint + # - gochecknoglobals + # - gocognit + # - godot + # - godox + # - goerr113 + # - interfacer + # - maligned + # - nestif + # - prealloc + # - testpackage + +issues: + exclude-use-default: false + exclude: + # for "public interface + private struct implementation" cases only! + - exported func * returns unexported type *, which can be annoying to use + - should have a package comment, unless it's in another file for this package + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - gocyclo + - funlen + - dupl + - gosec + - path: internal/input/ + linters: + - gocyclo + - funlen + - godot + - godox + - dupl + - gofmt + - gci + - gofumpt + - goimports + - gosimple + - path: internal/puzzles/constants.go + linters: + - revive + - path: internal/puzzles/solutions/ + linters: + - gochecknoinits + + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing + # large codebase. It's not practical to fix all existing issues at the moment + # of integration: much better don't allow issues in new code. + # Default is false. + new: true + + # Fix found issues (if it's supported by the linter) + fix: false + + severity: + # Default value is empty string. + # Set the default severity for issues. If severity rules are defined and the issues + # do not match or no severity is provided to the rule this will be the default + # severity applied. Severities should match the supported severity names of the + # selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity + # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + default-severity: error + + # The default value is false. + # If set to true severity-rules regular expressions become case sensitive. + case-sensitive: false + + # Default value is empty list. + # When a list of severity rules are provided, severity information will be added to lint + # issues. Severity rules have the same filtering capability as exclude rules except you + # are allowed to specify one matcher per severity rule. + # Only affects out formats that support setting severity information. + rules: + - linters: + - dupl + severity: warning + +run: + issues-exit-code: 0 + tests: true + skip-dirs: + - vendor/ + skip-files: + - \.pb\.go$ + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions + # default is "colored-line-number" + format: checkstyle + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true + + # make issues output unique by line, default is true + uniq-by-line: true + + # add a prefix to the output file references; default is no prefix + path-prefix: "" + + # sorts results by: filepath, line and column + sort-results: true diff --git a/vendor/github.com/obalunenko/getenv/.goreleaser.yml b/vendor/github.com/obalunenko/getenv/.goreleaser.yml new file mode 100644 index 000000000..b8b045810 --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/.goreleaser.yml @@ -0,0 +1,29 @@ +release: + github: + owner: obalunenko + name: getenv + +builds: + - skip: true + +checksum: + name_template: "{{ .ProjectName }}-{{ .Version }}-checksums.txt" + +snapshot: + name_template: SNAPSHOT-{{ .Commit }} + +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + - "README" + - "^readme" + - "^scripts" + - "scripts:" + - Merge pull request + - Merge branch + - Rebase on master + - "^Makefile" + - "goreleaser" diff --git a/vendor/github.com/obalunenko/getenv/LICENSE b/vendor/github.com/obalunenko/getenv/LICENSE new file mode 100644 index 000000000..cec79ac2c --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Oleg Balunenko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/obalunenko/getenv/Makefile b/vendor/github.com/obalunenko/getenv/Makefile new file mode 100644 index 000000000..48fe9b57c --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/Makefile @@ -0,0 +1,136 @@ +BIN_DIR=./bin + +SHELL := env VERSION=$(VERSION) $(SHELL) +VERSION ?= $(shell git describe --tags $(git rev-list --tags --max-count=1)) + +APP_NAME?=getenv +SHELL := env APP_NAME=$(APP_NAME) $(SHELL) + +GOTOOLS_IMAGE_TAG?=v0.0.2 +SHELL := env GOTOOLS_IMAGE_TAG=$(GOTOOLS_IMAGE_TAG) $(SHELL) + +COMPOSE_TOOLS_FILE=deployments/docker-compose/go-tools-docker-compose.yml +COMPOSE_TOOLS_CMD_BASE=docker compose -f $(COMPOSE_TOOLS_FILE) +COMPOSE_TOOLS_CMD_UP=$(COMPOSE_TOOLS_CMD_BASE) up --exit-code-from +COMPOSE_TOOLS_CMD_PULL=$(COMPOSE_TOOLS_CMD_BASE) pull + +TARGET_MAX_CHAR_NUM=20 + +## Show help +help: + ${call colored, help is running...} + @echo '' + @echo 'Usage:' + @echo ' make ' + @echo '' + @echo 'Targets:' + @awk '/^[a-zA-Z\-\_0-9]+:/ { \ + helpMessage = match(lastLine, /^## (.*)/); \ + if (helpMessage) { \ + helpCommand = substr($$1, 0, index($$1, ":")-1); \ + helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ + printf " %-$(TARGET_MAX_CHAR_NUM)s %s\n", helpCommand, helpMessage; \ + } \ + } \ + { lastLine = $$0 }' $(MAKEFILE_LIST) + + +## Test coverage report. +test-cover: vet + $(COMPOSE_TOOLS_CMD_UP) run-tests-coverage run-tests-coverage +.PHONY: test-cover + +## Tests sonar report generate. +test-sonar-report: + ./scripts/tests/sonar-report.sh +.PHONY: test-sonar-report + +## Open coverage report. +open-cover-report: test-cover + ./scripts/open-coverage-report.sh +.PHONY: open-cover-report + +## Update readme coverage. +update-readme-cover: test-cover + $(COMPOSE_TOOLS_CMD_UP) update-readme-coverage update-readme-coverage +.PHONY: update-readme-cover + +## Run tests. +test: + $(COMPOSE_TOOLS_CMD_UP) run-tests run-tests +.PHONY: test + +## Run regression tests. +test-regression: test +.PHONY: test-regression + +## Sync vendor and install needed tools. +configure: sync-vendor install-tools + +## Sync vendor with go.mod. +sync-vendor: + ./scripts/sync-vendor.sh +.PHONY: sync-vendor + +## Fix imports sorting. +imports: + $(COMPOSE_TOOLS_CMD_UP) fix-imports fix-imports +.PHONY: imports + +## Format code with go fmt. +fmt: + $(COMPOSE_TOOLS_CMD_UP) fix-fmt fix-fmt +.PHONY: fmt + +## Format code and sort imports. +format-project: fmt imports +.PHONY: format-project + +## Installs vendored tools. +install-tools: + echo "Installing ${GOTOOLS_IMAGE_TAG}" + $(COMPOSE_TOOLS_CMD_PULL) +.PHONY: install-tools + +## vet project +vet: + ./scripts/linting/run-vet.sh +.PHONY: vet + +## Run full linting +lint-full: + $(COMPOSE_TOOLS_CMD_UP) lint-full lint-full +.PHONY: lint-full + +## Run linting for build pipeline +lint-pipeline: + $(COMPOSE_TOOLS_CMD_UP) lint-pipeline lint-pipeline +.PHONY: lint-pipeline + +## Run linting for sonar report +lint-sonar: + $(COMPOSE_TOOLS_CMD_UP) lint-sonar lint-sonar +.PHONY: lint-sonar + +## Release +release: + ./scripts/release/release.sh +.PHONY: release + +## Release local snapshot +release-local-snapshot: + ./scripts/release/local-snapshot-release.sh +.PHONY: release-local-snapshot + +## Check goreleaser config. +check-releaser: + ./scripts/release/check.sh +.PHONY: check-releaser + +## Issue new release. +new-version: vet test-regression + ./scripts/release/new-version.sh +.PHONY: new-release + +.DEFAULT_GOAL := help + diff --git a/vendor/github.com/obalunenko/getenv/README.md b/vendor/github.com/obalunenko/getenv/README.md new file mode 100644 index 000000000..54bf6237e --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/README.md @@ -0,0 +1,13 @@ +![coverbadger-tag-do-not-edit](https://img.shields.io/badge/coverage-96.23%25-brightgreen?longCache=true&style=flat) + + +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/obalunenko/getenv) +[![Go Reference](https://pkg.go.dev/badge/github.com/obalunenko/getenv.svg)](https://pkg.go.dev/github.com/obalunenko/getenv) +[![Go Report Card](https://goreportcard.com/badge/github.com/obalunenko/getenv)](https://goreportcard.com/report/github.com/obalunenko/getenv) +[![codecov](https://codecov.io/gh/obalunenko/getenv/branch/master/graph/badge.svg)](https://codecov.io/gh/obalunenko/getenv) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=obalunenko_getenv&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=obalunenko_getenv) + + +# getenv + +Package getenv provides functionality for loading environment variables and parse them into go builtin types. diff --git a/vendor/github.com/obalunenko/getenv/getenv.go b/vendor/github.com/obalunenko/getenv/getenv.go new file mode 100644 index 000000000..e5c87555f --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/getenv.go @@ -0,0 +1,146 @@ +// Package getenv provides functionality for loading environment variables. +package getenv + +import ( + "os" + "strconv" + "strings" + "time" +) + +// IntOrDefault retrieves the int value of the environment variable named +// by the key. +// If variable not set or value is empty - defaultVal will be returned. +func IntOrDefault(key string, defaultVal int) int { + env := StringOrDefault(key, "") + if env == "" { + return defaultVal + } + + val, err := strconv.Atoi(env) + if err != nil { + return defaultVal + } + + return val +} + +// StringOrDefault retrieves the string value of the environment variable named +// by the key. +// If variable not set or value is empty - defaultVal will be returned. +func StringOrDefault(key, defaultVal string) string { + env, ok := os.LookupEnv(key) + if !ok || env == "" { + return defaultVal + } + + return env +} + +// BoolOrDefault retrieves the bool value of the environment variable named +// by the key. +// If variable not set or value is empty - defaultVal will be returned. +func BoolOrDefault(key string, defaultVal bool) bool { + env := StringOrDefault(key, "") + if env == "" { + return defaultVal + } + + val, err := strconv.ParseBool(env) + if err != nil { + return defaultVal + } + + return val +} + +// StringSliceOrDefault retrieves the string slice value of the environment variable named +// by the key and separated by sep. +// If variable not set or value is empty - defaultVal will be returned. +func StringSliceOrDefault(key string, defaultVal []string, sep string) []string { + env := StringOrDefault(key, "") + if env == "" { + return defaultVal + } + + val := strings.Split(env, sep) + + return val +} + +// DurationOrDefault retrieves the time.Duration value of the environment variable named +// by the key. +// If variable not set or value is empty - defaultVal will be returned. +func DurationOrDefault(key string, defaultVal time.Duration) time.Duration { + env := StringOrDefault(key, "") + if env == "" { + return defaultVal + } + + val, err := time.ParseDuration(env) + if err != nil { + return defaultVal + } + + return val +} + +// TimeOrDefault retrieves the time.Time value of the environment variable named +// by the key represented by layout. +// If variable not set or value is empty - defaultVal will be returned. +func TimeOrDefault(key string, defaultVal time.Time, layout string) time.Time { + env := StringOrDefault(key, "") + if env == "" { + return defaultVal + } + + val, err := time.Parse(layout, env) + if err != nil { + return defaultVal + } + + return val +} + +// Int64OrDefault retrieves the int64 value of the environment variable named +// by the key. +// If variable not set or value is empty - defaultVal will be returned. +func Int64OrDefault(key string, defaultVal int64) int64 { + env := StringOrDefault(key, "") + if env == "" { + return defaultVal + } + + const ( + base = 10 + bitsize = 64 + ) + + val, err := strconv.ParseInt(env, base, bitsize) + if err != nil { + return defaultVal + } + + return val +} + +// Float64OrDefault retrieves the float64 value of the environment variable named +// by the key. +// If variable not set or value is empty - defaultVal will be returned. +func Float64OrDefault(key string, defaultVal float64) float64 { + env := StringOrDefault(key, "") + if env == "" { + return defaultVal + } + + const ( + bitsize = 64 + ) + + val, err := strconv.ParseFloat(env, bitsize) + if err != nil { + return defaultVal + } + + return val +} diff --git a/vendor/github.com/obalunenko/getenv/sonar-project.properties b/vendor/github.com/obalunenko/getenv/sonar-project.properties new file mode 100644 index 000000000..d42c7a414 --- /dev/null +++ b/vendor/github.com/obalunenko/getenv/sonar-project.properties @@ -0,0 +1,33 @@ +# ===================================================== +# Standard properties +# ===================================================== + +sonar.projectKey=obalunenko_getenv +sonar.projectName=getenv +sonar.organization=obalunenko +sonar.projectVersion=1.0 + +sonar.host.url=https://sonarcloud.io +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +# This property is optional if sonar.modules is set. +sonar.sources=. +sonar.exclusions=**/*_test.go,**/vendor/** + +sonar.tests=. +sonar.test.inclusions=**/*_test.go +sonar.test.exclusions=**/vendor/** +# ===================================================== +# Meta-data for the project +# ===================================================== + +sonar.links.homepage=https://github.com/obalunenko/getenv +sonar.links.ci=https://github.com/obalunenko/getenv/actions +sonar.links.issue=https://github.com/obalunenko/getenv/issues + +# ===================================================== +# Properties specific to Go +# ===================================================== + +sonar.go.golangci-lint.reportPaths=linters.out +sonar.go.tests.reportPaths=tests-report.json +sonar.go.coverage.reportPaths=coverage/full.cov \ No newline at end of file diff --git a/vendor/github.com/olegfedoseev/image-diff/.gitignore b/vendor/github.com/olegfedoseev/image-diff/.gitignore new file mode 100644 index 000000000..a1338d685 --- /dev/null +++ b/vendor/github.com/olegfedoseev/image-diff/.gitignore @@ -0,0 +1,14 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ diff --git a/vendor/github.com/olegfedoseev/image-diff/LICENSE b/vendor/github.com/olegfedoseev/image-diff/LICENSE new file mode 100644 index 000000000..17dbf9684 --- /dev/null +++ b/vendor/github.com/olegfedoseev/image-diff/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Oleg Fedoseev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/olegfedoseev/image-diff/README.md b/vendor/github.com/olegfedoseev/image-diff/README.md new file mode 100644 index 000000000..1b41000b3 --- /dev/null +++ b/vendor/github.com/olegfedoseev/image-diff/README.md @@ -0,0 +1,34 @@ +# image-diff +[![Go Report Card](https://goreportcard.com/badge/github.com/olegfedoseev/image-diff)](https://goreportcard.com/report/github.com/olegfedoseev/image-diff) + +Allow you to calculate the difference between two images. Primarily for documents for now. + + +You give it first image, like that: + +![test-only-text](testdata/test-only-text.png?raw=true "test-only-text") + +And second one: + +![test-text-number](testdata/test-text-number.png?raw=true "test-text-number") + +And you get diff percent (6.25%) and visual diff: + +![diff](testdata/diff.png?raw=true "diff") + +# How to get and use + +``` +go get -u github.com/olegfedoseev/image-diff +``` + +And in you code: + +``` +import "github.com/olegfedoseev/image-diff" + +diff, percent, err := diff.CompareFiles("test-only-text.png", "test-text-number.png") +if percent > 0.0 { + fmt.Printf("images is different!") +} +``` diff --git a/vendor/github.com/olegfedoseev/image-diff/diff.go b/vendor/github.com/olegfedoseev/image-diff/diff.go new file mode 100644 index 000000000..8a42b00d5 --- /dev/null +++ b/vendor/github.com/olegfedoseev/image-diff/diff.go @@ -0,0 +1,73 @@ +package diff + +import ( + "errors" + "image" + "image/color" + "os" +) + +// CompareFiles will load images from files and then compare it with CompareImages +func CompareFiles(src, dst string) (diff image.Image, percent float64, err error) { + srcImage, err := loadImage(src) + if err != nil { + return nil, 0, err + } + dstImage, err := loadImage(dst) + if err != nil { + return nil, 0, err + } + return CompareImages(srcImage, dstImage) +} + +// CompareImages will check images size and pixel by pixel difference +func CompareImages(src, dst image.Image) (diff image.Image, percent float64, err error) { + srcBounds := src.Bounds() + dstBounds := dst.Bounds() + if !boundsMatch(srcBounds, dstBounds) { + return nil, 100.0, errors.New("image sizes don't match") + } + + diffImage := image.NewRGBA(image.Rect(0, 0, srcBounds.Max.X, srcBounds.Max.Y)) + + var differentPixels float64 + for y := srcBounds.Min.Y; y < srcBounds.Max.Y; y++ { + for x := srcBounds.Min.X; x < srcBounds.Max.X; x++ { + r, g, b, _ := dst.At(x, y).RGBA() + diffImage.Set(x, y, color.RGBA{uint8(r), uint8(g), uint8(b), 64}) + + if !isEqualColor(src.At(x, y), dst.At(x, y)) { + differentPixels++ + // Add red dot in diff image + diffImage.Set(x, y, color.RGBA{255, 0, 0, 255}) + } + } + } + + diffPercent := differentPixels / float64(srcBounds.Max.X*srcBounds.Max.Y) * 100 + return diffImage, diffPercent, nil +} + +func isEqualColor(a, b color.Color) bool { + r1, g1, b1, a1 := a.RGBA() + r2, g2, b2, a2 := b.RGBA() + + return r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2 +} + +func boundsMatch(a, b image.Rectangle) bool { + return a.Min.X == b.Min.X && a.Min.Y == b.Min.Y && a.Max.X == b.Max.X && a.Max.Y == b.Max.Y +} + +func loadImage(filename string) (image.Image, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + img, _, err := image.Decode(f) + if err != nil { + return nil, err + } + return img, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 899b995c0..b3e3d011c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -214,12 +214,18 @@ github.com/moby/term/windows # github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe ## explicit github.com/montanaflynn/stats +# github.com/obalunenko/getenv v1.1.0 +## explicit; go 1.19 +github.com/obalunenko/getenv # github.com/obalunenko/logger v0.5.1 ## explicit; go 1.18 github.com/obalunenko/logger # github.com/obalunenko/version v1.1.0 ## explicit; go 1.17 github.com/obalunenko/version +# github.com/olegfedoseev/image-diff v0.0.0-20171116094004-897a4e73dfd6 +## explicit +github.com/olegfedoseev/image-diff # github.com/opencontainers/go-digest v1.0.0 ## explicit; go 1.13 github.com/opencontainers/go-digest