package format import ( "testing" "time" ) func TestParseExifFull(t *testing.T) { data := []byte(`[{ "SourceFile": "a.jpg", "ImageWidth": 6240, "ImageHeight": 4160, "Orientation": 1, "DateTimeOriginal": "2025:03:14 23:10:05", "Make": "FUJIFILM", "Model": "X-T5", "LensModel": "XF23mmF2 R WR", "FNumber": 2, "ExposureTime": 0.008, "ISO": 1600 }]`) m, err := parseExif(data) if err != nil { t.Fatal(err) } want := Meta{ Width: 6240, Height: 4160, Taken: time.Date(2025, 3, 14, 23, 10, 5, 0, time.UTC), Camera: "FUJIFILM X-T5", Lens: "XF23mmF2 R WR", Aperture: "f/2", Shutter: "1/125", ISO: 1600, } if m != want { t.Fatalf("got %+v\nwant %+v", m, want) } } func TestParseExifRotatedSwapsDimensions(t *testing.T) { for _, o := range []string{"5", "6", "7", "8"} { m, err := parseExif([]byte(`[{"ImageWidth": 300, "ImageHeight": 200, "Orientation": ` + o + `}]`)) if err != nil { t.Fatal(err) } if m.Width != 200 || m.Height != 300 { t.Errorf("orientation %s: got %dx%d, want 200x300", o, m.Width, m.Height) } } } func TestParseExifFallbacks(t *testing.T) { m, err := parseExif([]byte(`[{ "ImageWidth": 10, "ImageHeight": 10, "CreateDate": "2024:01:02 03:04:05+01:00", "Make": "Canon", "Model": "Canon EOS R6", "FNumber": 5.6, "ExposureTime": 2 }]`)) if err != nil { t.Fatal(err) } if want := time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC); !m.Taken.Equal(want) { t.Errorf("Taken = %v, want %v", m.Taken, want) } if m.Camera != "Canon EOS R6" { t.Errorf("Camera = %q", m.Camera) } if m.Aperture != "f/5.6" || m.Shutter != "2s" { t.Errorf("Aperture %q Shutter %q", m.Aperture, m.Shutter) } } func TestParseExifMinimal(t *testing.T) { m, err := parseExif([]byte(`[{"ImageWidth": 120, "ImageHeight": 80}]`)) if err != nil { t.Fatal(err) } if (m != Meta{Width: 120, Height: 80}) { t.Fatalf("got %+v", m) } } func TestParseExifErrors(t *testing.T) { for _, in := range []string{`not json`, `[]`, `[{}, {}]`, `[{"ImageWidth": 10}]`} { if _, err := parseExif([]byte(in)); err == nil { t.Errorf("%s: want error", in) } } } func TestParseExifRoundsAperture(t *testing.T) { for in, want := range map[string]string{"1.779999971": "f/1.8", "2": "f/2", "5.6": "f/5.6", "11": "f/11", "22": "f/22", "0.95": "f/0.95"} { m, err := parseExif([]byte(`[{"ImageWidth": 1, "ImageHeight": 1, "FNumber": ` + in + `}]`)) if err != nil { t.Fatal(err) } if m.Aperture != want { t.Errorf("FNumber %s: got %q, want %q", in, m.Aperture, want) } } }