11package provider
22
33import (
4+ "bytes"
45 "encoding/base64"
56 "encoding/json"
7+ "image"
68 "image-gen-service/internal/model"
9+ "image/color"
10+ "image/jpeg"
11+ "io"
712 "net/http"
813 "net/http/httptest"
914 "strings"
@@ -188,6 +193,7 @@ func TestOpenAIImageProviderGenerateWithReferenceUsesEdits(t *testing.T) {
188193 "model_id" : "gpt-image-2-all" ,
189194 "aspect_ratio" : "1:1" ,
190195 "resolution_level" : "1K" ,
196+ "quality" : "high" ,
191197 "count" : 1 ,
192198 "reference_images" : []interface {}{refBytes , refBytes , refBytes },
193199 })
@@ -200,6 +206,9 @@ func TestOpenAIImageProviderGenerateWithReferenceUsesEdits(t *testing.T) {
200206 if seenFields ["model" ] != "gpt-image-2-all" || seenFields ["prompt" ] != "edit prompt" || seenFields ["size" ] != "1280x1280" {
201207 t .Fatalf ("unexpected fields: %+v" , seenFields )
202208 }
209+ if seenFields ["quality" ] != "high" {
210+ t .Fatalf ("quality = %q, want high" , seenFields ["quality" ])
211+ }
203212 if _ , ok := seenFields ["input_fidelity" ]; ok {
204213 t .Fatalf ("input_fidelity should not be sent to edits: %+v" , seenFields )
205214 }
@@ -214,10 +223,45 @@ func TestOpenAIImageProviderGenerateWithReferenceUsesEdits(t *testing.T) {
214223 }
215224}
216225
217- func TestOpenAIImageProviderRejectsNonPNGReference (t * testing.T ) {
226+ func TestOpenAIImageProviderConvertsJPEGReferenceToPNG (t * testing.T ) {
227+ var jpegRef bytes.Buffer
228+ img := image .NewRGBA (image .Rect (0 , 0 , 1 , 1 ))
229+ img .Set (0 , 0 , color .White )
230+ if err := jpeg .Encode (& jpegRef , img , nil ); err != nil {
231+ t .Fatalf ("encode jpeg: %v" , err )
232+ }
233+
234+ var seenImageContentType string
235+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
236+ if err := r .ParseMultipartForm (2 << 20 ); err != nil {
237+ t .Fatalf ("ParseMultipartForm: %v" , err )
238+ }
239+ files := r .MultipartForm .File ["image" ]
240+ if len (files ) != 1 {
241+ t .Fatalf ("image files = %d, want 1" , len (files ))
242+ }
243+ seenImageContentType = files [0 ].Header .Get ("Content-Type" )
244+ file , err := files [0 ].Open ()
245+ if err != nil {
246+ t .Fatalf ("open image part: %v" , err )
247+ }
248+ defer file .Close ()
249+ content , err := io .ReadAll (file )
250+ if err != nil {
251+ t .Fatalf ("read image part: %v" , err )
252+ }
253+ if http .DetectContentType (content ) != "image/png" {
254+ t .Fatalf ("uploaded content type = %q, want image/png" , http .DetectContentType (content ))
255+ }
256+ _ = json .NewEncoder (w ).Encode (map [string ]interface {}{
257+ "data" : []map [string ]string {{"b64_json" : tinyPNGBase64 }},
258+ })
259+ }))
260+ defer server .Close ()
261+
218262 p , err := NewOpenAIImageProvider (& model.ProviderConfig {
219263 ProviderName : "openai-image" ,
220- APIBase : "http://example.test/v1" ,
264+ APIBase : server . URL ,
221265 APIKey : "test-key" ,
222266 TimeoutSeconds : 5 ,
223267 })
@@ -231,9 +275,19 @@ func TestOpenAIImageProviderRejectsNonPNGReference(t *testing.T) {
231275 "aspect_ratio" : "1:1" ,
232276 "resolution_level" : "1K" ,
233277 "count" : 1 ,
234- "reference_images" : []interface {}{[] byte ( "not an image" )},
278+ "reference_images" : []interface {}{jpegRef . Bytes ( )},
235279 })
236- if err == nil || ! strings .Contains (err .Error (), "OpenAI Edit 仅支持 PNG 格式" ) {
237- t .Fatalf ("Generate error = %v, want PNG validation error" , err )
280+ if err != nil {
281+ t .Fatalf ("Generate: %v" , err )
282+ }
283+ if seenImageContentType != "image/png" {
284+ t .Fatalf ("image part Content-Type = %q, want image/png" , seenImageContentType )
285+ }
286+ }
287+
288+ func TestOpenAIImageProviderRejectsInvalidReference (t * testing.T ) {
289+ _ , err := collectOpenAIImageReferences ([]interface {}{[]byte ("not an image" )})
290+ if err == nil || ! strings .Contains (err .Error (), "不是有效图片" ) {
291+ t .Fatalf ("collectOpenAIImageReferences error = %v, want invalid image error" , err )
238292 }
239293}
0 commit comments