feat: add file handler e2e tests covering GET, PUT, index, auth, and 404
Adds 5 test methods (7 test cases) for the file handler: GET existing file, GET nonexistent file, GET index.html, PUT upload, PUT without permission, and auth (no-auth-401, with-auth-success). Includes test data files and server YAML configs under tests/e2e/testdata/file/.
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
)
|
||||
|
||||
type FileSuite struct {
|
||||
suite.Suite
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (s *FileSuite) SetupSuite() {
|
||||
s.ctx = context.Background()
|
||||
}
|
||||
|
||||
func (s *FileSuite) TearDownSuite() {}
|
||||
|
||||
// TestFileGetExisting verifies that GET on an existing file returns
|
||||
// the file content with HTTP 200. Covers the basic file serving path:
|
||||
// file handler → http.FileServer → file read.
|
||||
func (s *FileSuite) TestFileGetExisting() {
|
||||
gostC, err := RunGostContainerWithFiles(s.ctx, SharedNetworkName,
|
||||
"testdata/file/server.yaml",
|
||||
[]testcontainers.ContainerFile{
|
||||
{HostFilePath: "testdata/file/hello.txt", ContainerFilePath: "/srv/files/hello.txt", FileMode: 0644},
|
||||
},
|
||||
"8080/tcp")
|
||||
s.Require().NoError(err)
|
||||
defer gostC.Terminate(s.ctx)
|
||||
|
||||
cmd := []string{"curl", "-v", "-s", "http://127.0.0.1:8080/hello.txt"}
|
||||
code, out, err := gostC.Exec(s.ctx, cmd)
|
||||
s.Require().NoError(err)
|
||||
|
||||
body, err := io.ReadAll(out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
if code != 0 || !strings.Contains(string(body), "hello-gost-file") {
|
||||
DumpLogs(s.T(), s.ctx, "file-server logs", gostC)
|
||||
}
|
||||
s.Require().Equal(0, code)
|
||||
s.Require().Contains(string(body), "hello-gost-file")
|
||||
}
|
||||
|
||||
// TestFileGetNotFound verifies that GET on a nonexistent file returns
|
||||
// 404 Not Found.
|
||||
func (s *FileSuite) TestFileGetNotFound() {
|
||||
gostC, err := RunGostContainerWithFiles(s.ctx, SharedNetworkName,
|
||||
"testdata/file/server.yaml",
|
||||
[]testcontainers.ContainerFile{
|
||||
{HostFilePath: "testdata/file/hello.txt", ContainerFilePath: "/srv/files/hello.txt", FileMode: 0644},
|
||||
},
|
||||
"8080/tcp")
|
||||
s.Require().NoError(err)
|
||||
defer gostC.Terminate(s.ctx)
|
||||
|
||||
cmd := []string{"curl", "-v", "-s", "-o", "/dev/null", "-w", "%{http_code}",
|
||||
"http://127.0.0.1:8080/nonexistent.txt"}
|
||||
_, out, err := gostC.Exec(s.ctx, cmd)
|
||||
s.Require().NoError(err)
|
||||
body, _ := io.ReadAll(out)
|
||||
s.Assert().Contains(string(body), "404")
|
||||
}
|
||||
|
||||
// TestFileGetIndexHtml verifies that GET / serves index.html when
|
||||
// present in the served directory. Covers the default index document
|
||||
// behavior of http.FileServer.
|
||||
func (s *FileSuite) TestFileGetIndexHtml() {
|
||||
gostC, err := RunGostContainerWithFiles(s.ctx, SharedNetworkName,
|
||||
"testdata/file/server.yaml",
|
||||
[]testcontainers.ContainerFile{
|
||||
{HostFilePath: "testdata/file/index.html", ContainerFilePath: "/srv/files/index.html", FileMode: 0644},
|
||||
},
|
||||
"8080/tcp")
|
||||
s.Require().NoError(err)
|
||||
defer gostC.Terminate(s.ctx)
|
||||
|
||||
cmd := []string{"curl", "-v", "-s", "http://127.0.0.1:8080/"}
|
||||
code, out, err := gostC.Exec(s.ctx, cmd)
|
||||
s.Require().NoError(err)
|
||||
|
||||
body, err := io.ReadAll(out)
|
||||
s.Require().NoError(err)
|
||||
if code != 0 || !strings.Contains(string(body), "gost file index") {
|
||||
DumpLogs(s.T(), s.ctx, "file-server index logs", gostC)
|
||||
}
|
||||
s.Require().Equal(0, code)
|
||||
s.Require().Contains(string(body), "gost file index")
|
||||
}
|
||||
|
||||
// TestFilePutUpload verifies that PUT uploads a file when file.put is
|
||||
// enabled. Uploads a file and then reads it back via GET to confirm
|
||||
// the content was persisted.
|
||||
func (s *FileSuite) TestFilePutUpload() {
|
||||
gostC, err := RunGostContainerWithFiles(s.ctx, SharedNetworkName,
|
||||
"testdata/file/server_put.yaml",
|
||||
[]testcontainers.ContainerFile{
|
||||
{HostFilePath: "testdata/file/.empty", ContainerFilePath: "/srv/files/.empty", FileMode: 0644},
|
||||
},
|
||||
"8080/tcp")
|
||||
s.Require().NoError(err)
|
||||
defer gostC.Terminate(s.ctx)
|
||||
|
||||
// Create source content inside the container.
|
||||
_, _, err = gostC.Exec(s.ctx, []string{
|
||||
"sh", "-c", "printf 'uploaded-content' > /tmp/upload_src.txt",
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Upload via PUT.
|
||||
_, out, err := gostC.Exec(s.ctx, []string{
|
||||
"curl", "-v", "-s", "-T", "/tmp/upload_src.txt",
|
||||
"http://127.0.0.1:8080/uploaded.txt",
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
putBody, _ := io.ReadAll(out)
|
||||
s.T().Logf("PUT response:\n%s", string(putBody))
|
||||
|
||||
// Read back the uploaded file via GET.
|
||||
_, out2, err := gostC.Exec(s.ctx, []string{
|
||||
"curl", "-v", "-s",
|
||||
"http://127.0.0.1:8080/uploaded.txt",
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
body, _ := io.ReadAll(out2)
|
||||
s.Assert().Contains(string(body), "uploaded-content")
|
||||
}
|
||||
|
||||
// TestFilePutNoPermission verifies that PUT returns 405 Method Not
|
||||
// Allowed when file.put is not enabled (default: false).
|
||||
func (s *FileSuite) TestFilePutNoPermission() {
|
||||
gostC, err := RunGostContainerWithFiles(s.ctx, SharedNetworkName,
|
||||
"testdata/file/server.yaml",
|
||||
[]testcontainers.ContainerFile{
|
||||
{HostFilePath: "testdata/file/.empty", ContainerFilePath: "/srv/files/.empty", FileMode: 0644},
|
||||
},
|
||||
"8080/tcp")
|
||||
s.Require().NoError(err)
|
||||
defer gostC.Terminate(s.ctx)
|
||||
|
||||
cmd := []string{"curl", "-v", "-s", "-o", "/dev/null", "-w", "%{http_code}",
|
||||
"-T", "/dev/null", "http://127.0.0.1:8080/test.txt"}
|
||||
_, out, err := gostC.Exec(s.ctx, cmd)
|
||||
s.Require().NoError(err)
|
||||
body, _ := io.ReadAll(out)
|
||||
s.Assert().Contains(string(body), "405")
|
||||
}
|
||||
|
||||
// TestFileAuth verifies authentication on the file handler.
|
||||
// Without credentials the handler returns 401 Unauthorized,
|
||||
// with valid credentials it serves the file.
|
||||
func (s *FileSuite) TestFileAuth() {
|
||||
gostC, err := RunGostContainerWithFiles(s.ctx, SharedNetworkName,
|
||||
"testdata/file/server_auth.yaml",
|
||||
[]testcontainers.ContainerFile{
|
||||
{HostFilePath: "testdata/file/hello.txt", ContainerFilePath: "/srv/files/hello.txt", FileMode: 0644},
|
||||
},
|
||||
"8080/tcp")
|
||||
s.Require().NoError(err)
|
||||
defer gostC.Terminate(s.ctx)
|
||||
|
||||
s.T().Run("no-auth-401", func(t *testing.T) {
|
||||
cmd := []string{"curl", "-v", "-s", "-o", "/dev/null", "-w", "%{http_code}",
|
||||
"http://127.0.0.1:8080/hello.txt"}
|
||||
_, out, _ := gostC.Exec(s.ctx, cmd)
|
||||
body, _ := io.ReadAll(out)
|
||||
s.Assert().Contains(string(body), "401")
|
||||
})
|
||||
|
||||
s.T().Run("with-auth-success", func(t *testing.T) {
|
||||
cmd := []string{"curl", "-v", "-s", "-u", "user:pass",
|
||||
"http://127.0.0.1:8080/hello.txt"}
|
||||
code, out, err := gostC.Exec(s.ctx, cmd)
|
||||
s.Require().NoError(err)
|
||||
|
||||
body, err := io.ReadAll(out)
|
||||
s.Require().NoError(err)
|
||||
if code != 0 || !strings.Contains(string(body), "hello-gost-file") {
|
||||
DumpLogs(s.T(), s.ctx, "file-server auth logs", gostC)
|
||||
}
|
||||
s.Require().Equal(0, code)
|
||||
s.Require().Contains(string(body), "hello-gost-file")
|
||||
})
|
||||
}
|
||||
|
||||
func TestFileSuite(t *testing.T) {
|
||||
suite.Run(t, new(FileSuite))
|
||||
}
|
||||
Vendored
Vendored
+1
@@ -0,0 +1 @@
|
||||
<html><body>gost file index</body></html>
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
services:
|
||||
- name: file-server
|
||||
addr: :8080
|
||||
handler:
|
||||
type: file
|
||||
metadata:
|
||||
file.dir: /srv/files
|
||||
listener:
|
||||
type: tcp
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
- name: file-server-auth
|
||||
addr: :8080
|
||||
handler:
|
||||
type: file
|
||||
auther: auther-0
|
||||
metadata:
|
||||
file.dir: /srv/files
|
||||
listener:
|
||||
type: tcp
|
||||
authers:
|
||||
- name: auther-0
|
||||
auths:
|
||||
- username: user
|
||||
password: pass
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
services:
|
||||
- name: file-server-put
|
||||
addr: :8080
|
||||
handler:
|
||||
type: file
|
||||
metadata:
|
||||
file.dir: /srv/files
|
||||
file.put: true
|
||||
listener:
|
||||
type: tcp
|
||||
Reference in New Issue
Block a user