// Copyright 2022 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. package asset import ( "fmt" "strings" "time" "github.com/google/syzkaller/pkg/gcs" ) type objectUploadCallback func(req *uploadRequest) (*uploadResponse, error) type objectRemoveCallback func(url string) error type dummyObject struct { createdAt time.Time contentType string contentEncoding string } type dummyStorageBackend struct { currentTime time.Time objects map[string]*dummyObject objectUpload objectUploadCallback objectRemove objectRemoveCallback } func makeDummyStorageBackend() *dummyStorageBackend { return &dummyStorageBackend{ currentTime: time.Now(), objects: make(map[string]*dummyObject), } } type dummyWriteCloser struct { } func (dwc *dummyWriteCloser) Write(p []byte) (int, error) { return len(p), nil } func (dwc *dummyWriteCloser) Close() error { return nil } func (be *dummyStorageBackend) upload(req *uploadRequest) (*uploadResponse, error) { be.objects[req.savePath] = &dummyObject{ createdAt: be.currentTime, contentType: req.contentType, contentEncoding: req.contentEncoding, } if be.objectUpload != nil { return be.objectUpload(req) } return &uploadResponse{writer: &dummyWriteCloser{}, path: req.savePath}, nil } func (be *dummyStorageBackend) downloadURL(path string, publicURL bool) (string, error) { return "http://download/" + path, nil } func (be *dummyStorageBackend) getPath(url string) (string, error) { if strings.HasPrefix(url, "http://unknown-bucket/") { return "", ErrUnknownBucket } if strings.HasPrefix(url, "http://download/") { return strings.TrimPrefix(url, "http://download/"), nil } return "", fmt.Errorf("unknown URL format") } func (be *dummyStorageBackend) list() ([]*gcs.Object, error) { ret := []*gcs.Object{} for path, obj := range be.objects { ret = append(ret, &gcs.Object{ Path: path, CreatedAt: obj.createdAt, }) } return ret, nil } func (be *dummyStorageBackend) remove(path string) error { if be.objectRemove != nil { if err := be.objectRemove(path); err != nil { return err } } if _, ok := be.objects[path]; !ok { return ErrAssetDoesNotExist } delete(be.objects, path) return nil } func (be *dummyStorageBackend) hasOnly(paths []string) error { makeError := func() error { return fmt.Errorf("object sets are not equal; needed: %#v; uploaded: %#v", paths, be.objects) } if len(paths) != len(be.objects) { return makeError() } for _, path := range paths { if be.objects[path] == nil { return makeError() } } return nil }