// Copyright Earl Warren // Copyright Loïc Dachary // Copyright twenty-panda // SPDX-License-Identifier: MIT package hoverfly import ( "bytes" "fmt" "io" "net/http" "net/http/httptest" "net/url" "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type testNothing struct{} func (o testNothing) Run() (code int) { return 456 } type testSomething struct { t *testing.T } func (o *testSomething) Run() (code int) { return 123 } type testSimulate struct { t *testing.T } func (o testSimulate) Run() (code int) { return 789 } func verifyRequest(t *testing.T, serverURL, payload string) { t.Helper() proxyString, ok := os.LookupEnv("http_proxy") require.True(t, ok) proxyURL, err := url.Parse(proxyString) require.NoError(t, err) client := http.Client{} client.Transport = &http.Transport{ Proxy: func(req *http.Request) (*url.URL, error) { return http.ProxyURL(proxyURL)(req) }, } res, err := client.Get(serverURL) require.NoError(t, err) answer, err := io.ReadAll(res.Body) res.Body.Close() require.NoError(t, err) assert.Equal(t, payload, string(answer)) } func runServer(t *testing.T, payload string) (string, func()) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, payload) })) require.NotNil(t, ts) return ts.URL, ts.Close } func TestHoverfly(t *testing.T) { hoverfly := newHoverfly() var exitCode int exit = func(code int) { exitCode = code } saveDir := t.TempDir() getwd = func() (string, error) { return saveDir, nil } hoverfly.SetOutput(os.Stderr) // do not run hoverfly os.Unsetenv("HOVERFLY") hoverfly.Run(testNothing{}) assert.Equal(t, 456, exitCode) // run hoverfly and set the proxy os.Setenv("HOVERFLY", modeCapture) something := testSomething{t: t} hoverfly.Run(&something) assert.Equal(t, 123, exitCode) testname := "thetest" greeting := "Hello world" serverURL, shutdownServer := runServer(t, greeting) t.Run("capture requests and save them", func(t *testing.T) { os.Setenv("HOVERFLY", modeCapture) output := bytes.NewBuffer([]byte{}) hoverflySingleton.SetOutput(output) require.NoError(t, hoverflySingleton.setup()) cleanup := Run(t, testname) assert.Contains(t, output.String(), "capture mode") verifyRequest(t, serverURL, greeting) cleanup() simulationPath, err := hoverflySingleton.getSimulationPath(testname) require.NoError(t, err) simulation, err := os.ReadFile(simulationPath) require.NoError(t, err) assert.Contains(t, string(simulation), greeting) require.NoError(t, hoverflySingleton.teardown()) }) shutdownServer() t.Run("read saved request and simulate them", func(t *testing.T) { os.Setenv("HOVERFLY", modeSimulate) output := bytes.NewBuffer([]byte{}) hoverflySingleton.SetOutput(output) require.NoError(t, hoverflySingleton.setup()) cleanup := Run(t, testname) assert.Contains(t, output.String(), "simulate mode") verifyRequest(t, serverURL, greeting) cleanup() require.NoError(t, hoverflySingleton.teardown()) }) }