From 83e720e5a27538fc8d38ac3006fbae5af34b0883 Mon Sep 17 00:00:00 2001 From: William Perron Date: Tue, 27 Jun 2023 09:32:55 -0400 Subject: [PATCH] add integration test util --- go.mod | 4 + go.sum | 7 ++ integrationtest/README.md | 5 + integrationtest/assert_matches_text.go | 59 ++++++++++ integrationtest/assert_matches_text_test.go | 124 ++++++++++++++++++++ 5 files changed, 199 insertions(+) create mode 100644 integrationtest/README.md create mode 100644 integrationtest/assert_matches_text.go create mode 100644 integrationtest/assert_matches_text_test.go diff --git a/go.mod b/go.mod index 8dbfbb0..17f1303 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,11 @@ require go.opentelemetry.io/otel/sdk v1.14.0 require ( github.com/cenkalti/backoff/v4 v4.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect @@ -16,6 +19,7 @@ require ( google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( diff --git a/go.sum b/go.sum index fb8884c..36d445a 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -133,6 +135,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -142,6 +145,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -423,6 +428,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/integrationtest/README.md b/integrationtest/README.md new file mode 100644 index 0000000..e20e791 --- /dev/null +++ b/integrationtest/README.md @@ -0,0 +1,5 @@ +# Integration Test Util + +Based off of Deno's internal integration test utilities. This is meant to test +external systems that are hard to mock or can't rely fully on dependency +injection. diff --git a/integrationtest/assert_matches_text.go b/integrationtest/assert_matches_text.go new file mode 100644 index 0000000..3bcc60d --- /dev/null +++ b/integrationtest/assert_matches_text.go @@ -0,0 +1,59 @@ +package integrationtest + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +const WILDCARD = "[WILDCARD]" + +func AssertMatchesText(t *testing.T, expected, actual string) { + if !strings.Contains(expected, WILDCARD) { + assert.Equal(t, expected, actual) + } else if !wildcardMatch(expected, actual) { + t.Errorf("texts do not match. expected \"%s\", got \"%s\"", expected, actual) + } +} + +func wildcardMatch(expected, actual string) bool { + return patternMatch(expected, actual, WILDCARD) +} + +func patternMatch(expected, actual, pattern string) bool { + if expected == pattern { + return true + } + + parts := strings.Split(expected, pattern) + if len(parts) == 1 { + return expected == actual + } + + if !strings.HasPrefix(actual, parts[0]) { + return false + } + + if lines := strings.Split(expected, "\n"); len(lines) > 0 && lines[0] == pattern { + actual = "\n" + actual + } + + t := []string{actual[:len(parts[0])], actual[len(parts[0]):]} + for i, part := range parts { + if i == 0 { + continue + } + + if i == len(parts)-1 && (part == "" || part == "\n") { + return true + } + + if found := strings.Index(t[1], part); found != -1 { + t = []string{t[1][:found+len(part)], t[1][found+len(part):]} + } else { + return false + } + } + return t[1] == "" +} diff --git a/integrationtest/assert_matches_text_test.go b/integrationtest/assert_matches_text_test.go new file mode 100644 index 0000000..e80f266 --- /dev/null +++ b/integrationtest/assert_matches_text_test.go @@ -0,0 +1,124 @@ +package integrationtest + +import ( + "testing" +) + +func Test_patternMatch(t *testing.T) { + type args struct { + expected string + actual string + pattern string + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "foobarbaz matches", + args: args{ + expected: "foo[BAR]baz", + actual: "foobarbaz", + pattern: "[BAR]", + }, + want: true, + }, + { + name: "foobarbaz does not match", + args: args{ + expected: "foo[BAR]baz", + actual: "foobazbar", + pattern: "[BAR]", + }, + want: false, + }, + { + name: "wildcard matches but not rest of string", + args: args{ + expected: "foo[BAR]baz", + actual: "foobarfizz", + pattern: "[BAR]", + }, + want: false, + }, + { + name: "just wildcard", + args: args{ + expected: "[BAR]", + actual: "foobarbaz", + pattern: "[BAR]", + }, + want: true, + }, + { + name: "prefix", + args: args{ + expected: "prefix[BAR]", + actual: "prefixbarbaz", + pattern: "[BAR]", + }, + want: true, + }, + { + name: "prefix does not match", + args: args{ + expected: "prefix[BAR]", + actual: "somethingelsebarbaz", + pattern: "[BAR]", + }, + want: false, + }, + { + name: "suffix", + args: args{ + expected: "[BAR]suffix", + actual: "foobarbazsuffix", + pattern: "[BAR]", + }, + want: true, + }, + { + name: "no pattern", + args: args{ + expected: "exact match", + actual: "exact match", + pattern: "[BAR]", + }, + want: true, + }, + { + name: "multiline", + args: args{ + expected: `first line +[BAR] +last line`, + actual: `first line +second line +last line`, + pattern: "[BAR]", + }, + want: true, + }, + { + name: "multiline prefix", + args: args{ + expected: `[BAR] +first line +last line`, + actual: `[BAR] +first line +last line`, + pattern: "[BAR]", + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := patternMatch(tt.args.expected, tt.args.actual, tt.args.pattern); got != tt.want { + t.Errorf("patternMatch() = %v, want %v", got, tt.want) + } + }) + } +}