gocustomurls/testUtils_test.go

261 lines
4.8 KiB
Go
Raw Permalink Normal View History

package main
import (
"bytes"
"encoding/json"
"errors"
"io"
"io/fs"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
)
func mkDirForTest(t *testing.T, fp string) {
err := os.MkdirAll(fp, os.ModePerm)
if err != nil {
t.Fatal(err)
}
}
func cpFileForTest(t *testing.T, src string, dst string) {
var srcfd *os.File
var dstfd *os.File
var err error
var srcinfo os.FileInfo
srcfd, err = os.Open(src)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return
} else {
t.Fatal(err)
}
}
// if err != nil {
// t.Fatal(err)
// }
defer srcfd.Close()
dstfd, err = os.Create(dst)
if err != nil {
t.Fatal(err)
}
defer dstfd.Close()
_, err = io.Copy(dstfd, srcfd)
if err != nil {
t.Fatal(err)
}
srcinfo, err = os.Stat(src)
if err != nil {
t.Fatal(err)
}
err = os.Chmod(dst, srcinfo.Mode())
if err != nil {
t.Fatal(err)
}
}
func writeForTest(t *testing.T, fp string, data []byte) {
err := os.WriteFile(fp, data, 0666)
if err != nil {
t.Fatal(err)
}
}
func IsDirEmpty(t *testing.T, name string) bool {
f, err := os.Open(name)
if err != nil {
t.Fatal(err)
}
defer f.Close()
// read in ONLY one file
_, err = f.Readdir(1)
// and if the file is EOF... well, the dir is empty.
return err == io.EOF
}
func doesFileExist(name string) bool {
_, err := os.ReadFile(name)
// defer fp.Close()
return err == nil
}
// Derived from here (https://stackoverflow.com/a/55300382)
func walkMatch(t *testing.T, root, pattern string) []string {
var matches []string
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if matched, err := filepath.Match(pattern, filepath.Base(path)); err != nil {
return err
} else if matched {
matches = append(matches, path)
}
return nil
})
if err != nil {
t.Fatal(err)
}
return matches
}
// func doesFileExist(name string) bool {
// _, err := os.Stat(name)
// return !errors.Is(err, fs.ErrNotExist)
// }
func removeFileForTest(t *testing.T, name string) {
err := os.Remove(name)
if err != nil {
t.Fatal(err)
}
}
func writeJsonForTest(t *testing.T, data map[string]any, fp string) {
jsonString, _ := json.Marshal(data)
err := os.WriteFile(fp, jsonString, os.ModePerm)
if err != nil {
t.Fatal(err)
}
}
func isFileEmpty(t *testing.T, name string) bool {
fd, err := os.Open(name)
if err != nil {
t.Fatal(err)
}
defer fd.Close()
finfo, err := fd.Stat()
if err != nil {
t.Fatal(err)
}
return finfo.Size() < 1
}
// Derived from here (https://stackoverflow.com/a/73411967)
func areFilesTheSame(t *testing.T, fp_1 string, fp_2 string) bool {
chunkSize := 4 * 1024
// shortcuts: check file metadata
finfo_1, err := os.Stat(fp_1)
if err != nil {
t.Fatal(err)
}
finfo_2, err := os.Stat(fp_2)
if err != nil {
t.Fatal(err)
}
// are inputs are literally the same file?
if os.SameFile(finfo_1, finfo_2) {
return true
}
// do inputs at least have the same size?
if finfo_1.Size() != finfo_2.Size() {
return false
}
// long way: compare contents
fd_1, err := os.Open(fp_1)
if err != nil {
t.Fatal(err)
}
defer fd_1.Close()
fd_2, err := os.Open(fp_2)
if err != nil {
t.Fatal(err)
}
defer fd_2.Close()
bfd_1 := make([]byte, chunkSize)
bfd_2 := make([]byte, chunkSize)
for {
n1, err1 := io.ReadFull(fd_1, bfd_1)
n2, err2 := io.ReadFull(fd_2, bfd_2)
// https://pkg.go.dev/io#Reader
// > Callers should always process the n > 0 bytes returned
// > before considering the error err. Doing so correctly
// > handles I/O errors that happen after reading some bytes
// > and also both of the allowed EOF behaviors.
if !bytes.Equal(bfd_1[:n1], bfd_2[:n2]) {
return false
}
if (err1 == io.EOF && err2 == io.EOF) || (err1 == io.ErrUnexpectedEOF && err2 == io.ErrUnexpectedEOF) {
return true
}
// some other error, like a dropped network connection or a bad transfer
if err1 != nil {
t.Fatal(err1)
}
if err2 != nil {
t.Fatal(err2)
}
}
}
func readTestFile(t *testing.T, fp string) []byte {
f, err := os.ReadFile(fp)
if err != nil {
t.Fatal(err)
}
return f
}
// func writeTestConfFile(t *testing.T, rulesPath string, logPath string) {
// writeJsonForTest(t, p, )
// }
// Integration tests
func newTestApp(t *testing.T, cfg *Config, lfg *LogFile) *Application {
return &Application{
Config: cfg,
Log: lfg,
}
}
type testServer struct {
*httptest.Server
}
func newTestServer(t *testing.T, h http.Handler) *testServer {
ts := httptest.NewServer(h)
return &testServer{ts}
}
func (ts *testServer) get(t *testing.T, urlPath string) (int, http.Header, []byte) {
rs, err := ts.Client().Get(ts.URL + urlPath)
if err != nil {
t.Fatal(err)
}
defer rs.Body.Close()
body, err := io.ReadAll(rs.Body)
if err != nil {
t.Fatal(err)
}
body = bytes.TrimSpace(body)
return rs.StatusCode, rs.Header, body
}