refactor: remove auto deposit penalty on no-shows, add comprehensive tests
- Remove automatic deposits_required=3 on no-shows, give admin flexibility - Add tests for no-show deposit logic (forgiven, over 24h, under 24h) - Add tests for reservation cleanup TTL (admin walk-in/call-in 15min) - Add tests for EXIF GPS data stripping in portfolio images - Add tests for contact info endpoint - Add tests for guest account anonymization
This commit is contained in:
@@ -19,6 +19,8 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"image"
|
||||
"image/color"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
@@ -29,6 +31,7 @@ import (
|
||||
"crussell/testutils/testdb"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/kovidgoyal/imaging"
|
||||
)
|
||||
|
||||
func setupTestDB(t *testing.T) func() {
|
||||
@@ -518,3 +521,91 @@ func TestPortfolio_Delete_Unauthenticated(t *testing.T) {
|
||||
t.Errorf("expected status 401, got %d. body: %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// processImage EXIF Stripping Tests
|
||||
// =============================================================================
|
||||
|
||||
// TestPortfolio_ProcessImage_EXIFStripped verifies that processImage strips EXIF GPS data from images.
|
||||
func TestPortfolio_ProcessImage_EXIFStripped(t *testing.T) {
|
||||
// Create a simple test image using the standard library
|
||||
img := image.NewNRGBA(image.Rect(0, 0, 100, 100))
|
||||
grayColor := color.RGBA{R: 200, G: 200, B: 200, A: 255}
|
||||
for y := 0; y < 100; y++ {
|
||||
for x := 0; x < 100; x++ {
|
||||
img.Set(x, y, grayColor)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode to JPEG bytes using imaging
|
||||
var buf bytes.Buffer
|
||||
err := imaging.Encode(&buf, img, imaging.JPEG, imaging.JPEGQuality(85))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to encode test image: %v", err)
|
||||
}
|
||||
imageBytes := buf.Bytes()
|
||||
|
||||
// Create a JPEG with embedded EXIF GPS data by appending GPS IFD marker after JPEG header
|
||||
// This creates a JPEG that claims to have GPS metadata
|
||||
gpsJpeg := createJpegWithExifMarker(imageBytes)
|
||||
if gpsJpeg == nil {
|
||||
t.Skip("Could not create JPEG with EXIF marker - using basic test")
|
||||
}
|
||||
|
||||
// Verify EXIF marker is present in the input
|
||||
hasExifBefore := bytes.Contains(gpsJpeg, []byte{0xFF, 0xE1}) // APP1 EXIF marker
|
||||
if !hasExifBefore {
|
||||
t.Skip("Could not inject EXIF marker - skipping GPS stripping test")
|
||||
}
|
||||
|
||||
// Process the image (this should strip EXIF/GPS data)
|
||||
result, err := processImage(gpsJpeg, 85)
|
||||
if err != nil {
|
||||
t.Fatalf("processImage failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify the result is a valid JPEG
|
||||
if len(result) == 0 {
|
||||
t.Fatal("processImage returned empty result")
|
||||
}
|
||||
|
||||
// Verify EXIF marker is NOT present in the output
|
||||
hasExifAfter := bytes.Contains(result, []byte{0xFF, 0xE1})
|
||||
if hasExifAfter {
|
||||
t.Error("EXIF data was NOT stripped by processImage - metadata still present")
|
||||
}
|
||||
}
|
||||
|
||||
// createJpegWithExifMarker creates a JPEG with an APP1 EXIF marker inserted after the SOI marker
|
||||
func createJpegWithExifMarker(jpegData []byte) []byte {
|
||||
if len(jpegData) < 2 || jpegData[0] != 0xFF || jpegData[1] != 0xD8 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a minimal APP1 EXIF marker with GPS IFD tag (0x8825)
|
||||
// APP1 marker: FF E1, length, "Exif\0\0", byte order, magic, IFD offset
|
||||
app1 := []byte{
|
||||
0xFF, 0xE1, // APP1 marker
|
||||
0x00, 0x22, // Length: 34 bytes
|
||||
// Exif header
|
||||
0x45, 0x78, 0x69, 0x66, 0x00, 0x00, // "Exif\0\0"
|
||||
0x49, 0x49, // Byte order: little-endian
|
||||
0x2A, 0x00, // Magic number
|
||||
0x08, 0x00, 0x00, 0x00, // Offset to first IFD
|
||||
// Main IFD with GPS IFD pointer
|
||||
0x01, 0x00, // Number of entries: 1
|
||||
0x25, 0x88, // GPS IFD tag (0x8825)
|
||||
0x04, 0x00, // Type: LONG
|
||||
0x01, 0x00, 0x00, 0x00, // Count: 1
|
||||
0x10, 0x00, 0x00, 0x00, // Offset: 16 (to GPS IFD)
|
||||
0x00, 0x00, 0x00, 0x00, // Next IFD: none
|
||||
}
|
||||
|
||||
// Insert APP1 after SOI marker (FF D8)
|
||||
result := make([]byte, 0, len(jpegData)+len(app1))
|
||||
result = append(result, jpegData[:2]...)
|
||||
result = append(result, app1...)
|
||||
result = append(result, jpegData[2:]...)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user