Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

661 lines
24 KiB
Go

package api
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
tuttigenerated "github.com/tutti-os/tutti/services/tuttid/api/generated"
"github.com/tutti-os/tutti/services/tuttid/apierrors"
workspacebiz "github.com/tutti-os/tutti/services/tuttid/biz/workspace"
workspaceservice "github.com/tutti-os/tutti/services/tuttid/service/workspace"
)
func TestDaemonAPIGeneratedRoutesListWorkspaceAppReferences(t *testing.T) {
mux := http.NewServeMux()
var gotWorkspaceID string
var gotAppID string
var gotInput workspacebiz.AppReferenceListInput
listCalls := 0
RegisterRoutes(
mux,
NewRoutes(DaemonAPI{
AppCenterService: stubWorkspaceAppCenterService{
listReferencesFn: func(_ context.Context, workspaceID string, appID string, input workspacebiz.AppReferenceListInput) (workspacebiz.AppReferenceListResult, error) {
listCalls++
gotWorkspaceID = workspaceID
gotAppID = appID
gotInput = input
return workspacebiz.AppReferenceListResult{}, nil
},
},
}),
)
recorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/docs/references/list",
map[string]any{
"parentGroupId": " group-1 ",
"filterText": " guide ",
"limit": 5,
"cursor": " cursor ",
"kinds": []string{"file"},
"timeRange": map[string]any{
"fromMs": 1000,
"toMs": 2000,
},
},
)
if recorder.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d: %s", recorder.Code, recorder.Body.String())
}
if listCalls != 1 {
t.Fatalf("expected one list call, got %d", listCalls)
}
if gotWorkspaceID != "workspace-1" {
t.Fatalf("expected workspace id workspace-1, got %q", gotWorkspaceID)
}
if gotAppID != "docs" {
t.Fatalf("expected app id docs, got %q", gotAppID)
}
if gotInput.ParentGroupID != "group-1" {
t.Fatalf("expected trimmed parentGroupId, got %q", gotInput.ParentGroupID)
}
if gotInput.FilterText != "guide" {
t.Fatalf("expected trimmed filterText, got %q", gotInput.FilterText)
}
if gotInput.Limit != 5 {
t.Fatalf("expected limit 5, got %d", gotInput.Limit)
}
if gotInput.Cursor != "cursor" {
t.Fatalf("expected trimmed cursor, got %q", gotInput.Cursor)
}
if len(gotInput.Kinds) != 1 || gotInput.Kinds[0] != workspacebiz.AppReferenceKindFile {
t.Fatalf("expected file kind filter, got %#v", gotInput.Kinds)
}
if gotInput.TimeRange == nil || gotInput.TimeRange.FromMs == nil || *gotInput.TimeRange.FromMs != 1000 || gotInput.TimeRange.ToMs == nil || *gotInput.TimeRange.ToMs != 2000 {
t.Fatalf("expected forwarded time range, got %#v", gotInput.TimeRange)
}
}
func TestDaemonAPIGeneratedRoutesListWorkspaceAppReferencesRejectsInvalidRequest(t *testing.T) {
tests := []struct {
name string
body map[string]any
}{
{
name: "blank parent group id",
body: map[string]any{"parentGroupId": " "},
},
{
name: "parent group id too long",
body: map[string]any{"parentGroupId": strings.Repeat("g", 2049)},
},
{
name: "filterText too long",
body: map[string]any{"filterText": strings.Repeat("x", 201)},
},
{
name: "limit below minimum",
body: map[string]any{"limit": 0},
},
{
name: "limit above maximum",
body: map[string]any{"limit": 201},
},
{
name: "cursor too long",
body: map[string]any{"cursor": strings.Repeat("c", 2049)},
},
{
name: "unknown kind",
body: map[string]any{"kinds": []string{"url"}},
},
{
name: "negative from",
body: map[string]any{"timeRange": map[string]any{"fromMs": -1}},
},
{
name: "negative to",
body: map[string]any{"timeRange": map[string]any{"toMs": -1}},
},
{
name: "from after to",
body: map[string]any{"timeRange": map[string]any{"fromMs": 2, "toMs": 1}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mux := http.NewServeMux()
listCalls := 0
RegisterRoutes(
mux,
NewRoutes(DaemonAPI{
AppCenterService: stubWorkspaceAppCenterService{
listReferencesFn: func(context.Context, string, string, workspacebiz.AppReferenceListInput) (workspacebiz.AppReferenceListResult, error) {
listCalls++
return workspacebiz.AppReferenceListResult{}, nil
},
},
}),
)
recorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/docs/references/list",
tt.body,
)
if recorder.Code != http.StatusBadRequest {
t.Fatalf("expected status 400, got %d: %s", recorder.Code, recorder.Body.String())
}
if listCalls != 0 {
t.Fatalf("expected list not to be called, got %d calls", listCalls)
}
})
}
}
func TestDaemonAPIGeneratedRoutesInstallWorkspaceAppPassesRestartOption(t *testing.T) {
mux := http.NewServeMux()
var gotWorkspaceID string
var gotAppID string
var gotOptions workspaceservice.InstallOptions
installCalls := 0
RegisterRoutes(
mux,
NewRoutes(DaemonAPI{
AppCenterService: stubWorkspaceAppCenterService{
installWithOptionsFn: func(_ context.Context, workspaceID string, appID string, options workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error) {
installCalls++
gotWorkspaceID = workspaceID
gotAppID = appID
gotOptions = options
return workspacebiz.WorkspaceApp{
Package: workspacebiz.AppPackage{
AppID: appID,
Version: "1.0.0",
PackageDir: "/tmp/app",
Manifest: workspacebiz.AppManifest{
AppID: appID,
Version: "1.0.0",
Name: "App",
Description: "",
},
Source: workspacebiz.AppPackageSourceBuiltin,
},
Runtime: workspacebiz.AppRuntimeState{Status: workspacebiz.AppRuntimeStatusIdle},
}, nil
},
},
}),
)
recorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/docs/install",
map[string]any{"restartRunning": true},
)
if recorder.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d: %s", recorder.Code, recorder.Body.String())
}
if installCalls != 1 {
t.Fatalf("expected one install call, got %d", installCalls)
}
if gotWorkspaceID != "workspace-1" || gotAppID != "docs" {
t.Fatalf("install target = %q/%q, want workspace-1/docs", gotWorkspaceID, gotAppID)
}
if !gotOptions.RestartRunning {
t.Fatal("RestartRunning = false, want true")
}
}
func TestDaemonAPIGeneratedRoutesLoadLocalWorkspaceAppPassesRequestAndReturnsLocalPackageDir(t *testing.T) {
mux := http.NewServeMux()
var gotWorkspaceID string
var gotSourceDir string
var gotOptions workspaceservice.InstallOptions
loadCalls := 0
RegisterRoutes(
mux,
NewRoutes(DaemonAPI{
AppCenterService: stubWorkspaceAppCenterService{
loadLocalPackageFn: func(_ context.Context, workspaceID string, sourceDir string, options workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error) {
loadCalls++
gotWorkspaceID = workspaceID
gotSourceDir = sourceDir
gotOptions = options
return workspacebiz.WorkspaceApp{
Package: workspacebiz.AppPackage{
AppID: "local-dev",
Version: "0.1.0",
PackageDir: "/Users/example/project/.tutti/dev-app",
Manifest: workspacebiz.AppManifest{
AppID: "local-dev",
Version: "0.1.0",
Name: "Local Dev",
Runtime: workspacebiz.AppManifestRuntime{
Bootstrap: "bootstrap.sh",
HealthcheckPath: "/",
},
},
Source: workspacebiz.AppPackageSourceLocalDev,
},
Installation: &workspacebiz.AppInstallation{WorkspaceID: workspaceID, AppID: "local-dev", Enabled: true},
Runtime: workspacebiz.AppRuntimeState{Status: workspacebiz.AppRuntimeStatusIdle},
}, nil
},
},
}),
)
recorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/load-local",
map[string]any{"sourceDir": "/Users/example/project"},
)
if recorder.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d: %s", recorder.Code, recorder.Body.String())
}
if loadCalls != 1 {
t.Fatalf("expected one load call, got %d", loadCalls)
}
if gotWorkspaceID != "workspace-1" || gotSourceDir != "/Users/example/project" {
t.Fatalf("load target = %q/%q", gotWorkspaceID, gotSourceDir)
}
if !gotOptions.RestartRunning {
t.Fatal("RestartRunning = false, want default true")
}
var payload struct {
App struct {
AppID string `json:"appId"`
LocalPackageDir *string `json:"localPackageDir"`
Source string `json:"source"`
} `json:"app"`
}
if err := json.Unmarshal(recorder.Body.Bytes(), &payload); err != nil {
t.Fatalf("unmarshal response: %v", err)
}
if payload.App.AppID != "local-dev" || payload.App.Source != "local-dev" {
t.Fatalf("response app = %#v", payload.App)
}
if payload.App.LocalPackageDir == nil || *payload.App.LocalPackageDir != "/Users/example/project/.tutti/dev-app" {
t.Fatalf("localPackageDir = %#v", payload.App.LocalPackageDir)
}
}
func TestDaemonAPIGeneratedRoutesReloadLocalWorkspaceAppPassesRestartOption(t *testing.T) {
mux := http.NewServeMux()
var gotWorkspaceID string
var gotAppID string
var gotOptions workspaceservice.InstallOptions
reloadCalls := 0
RegisterRoutes(
mux,
NewRoutes(DaemonAPI{
AppCenterService: stubWorkspaceAppCenterService{
reloadLocalPackageFn: func(_ context.Context, workspaceID string, appID string, options workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error) {
reloadCalls++
gotWorkspaceID = workspaceID
gotAppID = appID
gotOptions = options
return workspacebiz.WorkspaceApp{
Package: workspacebiz.AppPackage{
AppID: appID,
Version: "0.1.0",
PackageDir: "/Users/example/project/.tutti/dev-app",
Manifest: workspacebiz.AppManifest{
AppID: appID,
Version: "0.1.0",
Name: "Local Dev",
Runtime: workspacebiz.AppManifestRuntime{
Bootstrap: "bootstrap.sh",
HealthcheckPath: "/",
},
},
Source: workspacebiz.AppPackageSourceLocalDev,
},
Installation: &workspacebiz.AppInstallation{WorkspaceID: workspaceID, AppID: appID, Enabled: true},
Runtime: workspacebiz.AppRuntimeState{Status: workspacebiz.AppRuntimeStatusIdle},
}, nil
},
},
}),
)
recorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/local-dev/reload-local",
map[string]any{"restartRunning": false},
)
if recorder.Code != http.StatusOK {
t.Fatalf("expected status 200, got %d: %s", recorder.Code, recorder.Body.String())
}
if reloadCalls != 1 {
t.Fatalf("expected one reload call, got %d", reloadCalls)
}
if gotWorkspaceID != "workspace-1" || gotAppID != "local-dev" {
t.Fatalf("reload target = %q/%q", gotWorkspaceID, gotAppID)
}
if gotOptions.RestartRunning {
t.Fatal("RestartRunning = true, want false")
}
}
func TestDaemonAPIGeneratedRoutesWorkspaceAppUploadLifecycle(t *testing.T) {
mux := http.NewServeMux()
expiresAt := time.Date(2026, time.June, 24, 12, 15, 0, 0, time.UTC)
prepareCalls := 0
putCalls := 0
completeCalls := 0
cancelCalls := 0
RegisterRoutes(
mux,
NewRoutes(DaemonAPI{
AppCenterService: stubWorkspaceAppCenterService{
prepareWorkspaceAppUploadFn: func(_ context.Context, workspaceID string, appID string, input workspaceservice.PrepareWorkspaceAppUploadInput) (workspaceservice.WorkspaceAppUploadSession, error) {
prepareCalls++
if workspaceID != "workspace-1" || appID != "canvas" {
t.Fatalf("prepare target = %q/%q, want workspace-1/canvas", workspaceID, appID)
}
if input.Name != "image.png" || input.MimeType != "image/png" || input.SizeBytes != 5 || input.Purpose != workspaceservice.WorkspaceAppUploadPurposeAppAsset {
t.Fatalf("prepare input = %#v", input)
}
return workspaceservice.WorkspaceAppUploadSession{
ExpiresAt: expiresAt,
UploadID: "upload-1",
}, nil
},
putWorkspaceAppUploadContentFn: func(_ context.Context, workspaceID string, appID string, uploadID string, input workspaceservice.PutWorkspaceAppUploadContentInput) error {
putCalls++
if workspaceID != "workspace-1" || appID != "canvas" || uploadID != "upload-1" {
t.Fatalf("put target = %q/%q/%q, want workspace-1/canvas/upload-1", workspaceID, appID, uploadID)
}
data, err := io.ReadAll(input.Body)
if err != nil {
t.Fatalf("read upload body: %v", err)
}
if string(data) != "bytes" {
t.Fatalf("put body = %q, want bytes", data)
}
return nil
},
completeWorkspaceAppUploadFn: func(_ context.Context, workspaceID string, appID string, uploadID string, now time.Time) (workspaceservice.WorkspaceAppUploadedFile, error) {
completeCalls++
if workspaceID != "workspace-1" || appID != "canvas" || uploadID != "upload-1" {
t.Fatalf("complete target = %q/%q/%q, want workspace-1/canvas/upload-1", workspaceID, appID, uploadID)
}
if now.IsZero() {
t.Fatal("complete now is zero")
}
return workspaceservice.WorkspaceAppUploadedFile{
MimeType: "image/png",
Name: "image.png",
Path: "/state/apps/installations/canvas/data/uploads/2c/hash.png",
SHA256: "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
SizeBytes: 5,
}, nil
},
cancelWorkspaceAppUploadFn: func(_ context.Context, workspaceID string, appID string, uploadID string) error {
cancelCalls++
if workspaceID != "workspace-1" || appID != "canvas" || uploadID != "upload-1" {
t.Fatalf("cancel target = %q/%q/%q, want workspace-1/canvas/upload-1", workspaceID, appID, uploadID)
}
return nil
},
},
}),
)
prepareRecorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/canvas/uploads",
map[string]any{
"mimeType": "image/png",
"name": "image.png",
"purpose": "app-asset",
"sizeBytes": 5,
},
)
if prepareRecorder.Code != http.StatusCreated {
t.Fatalf("prepare status = %d, want %d; body: %s", prepareRecorder.Code, http.StatusCreated, prepareRecorder.Body.String())
}
var prepareResponse tuttigenerated.PrepareWorkspaceAppUploadResponse
decodeGeneratedRouteResponse(t, prepareRecorder, &prepareResponse)
if prepareResponse.UploadId != "upload-1" || !prepareResponse.ExpiresAt.Equal(expiresAt) {
t.Fatalf("prepare response = %#v", prepareResponse)
}
putRequest := httptest.NewRequest(http.MethodPut, "/v1/workspaces/workspace-1/apps/canvas/uploads/upload-1/content", strings.NewReader("bytes"))
putRequest.Header.Set("Content-Type", "application/octet-stream")
putRecorder := httptest.NewRecorder()
mux.ServeHTTP(putRecorder, putRequest)
if putRecorder.Code != http.StatusNoContent {
t.Fatalf("put status = %d, want %d; body: %s", putRecorder.Code, http.StatusNoContent, putRecorder.Body.String())
}
completeRecorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/canvas/uploads/upload-1/complete",
nil,
)
if completeRecorder.Code != http.StatusOK {
t.Fatalf("complete status = %d, want %d; body: %s", completeRecorder.Code, http.StatusOK, completeRecorder.Body.String())
}
var completeResponse tuttigenerated.CompleteWorkspaceAppUploadResponse
decodeGeneratedRouteResponse(t, completeRecorder, &completeResponse)
if completeResponse.File.Path != "/state/apps/installations/canvas/data/uploads/2c/hash.png" || completeResponse.File.SizeBytes != 5 {
t.Fatalf("complete response = %#v", completeResponse)
}
cancelRequest := httptest.NewRequest(http.MethodDelete, "/v1/workspaces/workspace-1/apps/canvas/uploads/upload-1", nil)
cancelRecorder := httptest.NewRecorder()
mux.ServeHTTP(cancelRecorder, cancelRequest)
if cancelRecorder.Code != http.StatusNoContent {
t.Fatalf("cancel status = %d, want %d; body: %s", cancelRecorder.Code, http.StatusNoContent, cancelRecorder.Body.String())
}
if prepareCalls != 1 || putCalls != 1 || completeCalls != 1 || cancelCalls != 1 {
t.Fatalf("calls = prepare:%d put:%d complete:%d cancel:%d, want 1 each", prepareCalls, putCalls, completeCalls, cancelCalls)
}
}
func TestDaemonAPIGeneratedRoutesCompleteWorkspaceAppUploadMapsNotReady(t *testing.T) {
mux := http.NewServeMux()
RegisterRoutes(
mux,
NewRoutes(DaemonAPI{
AppCenterService: stubWorkspaceAppCenterService{
completeWorkspaceAppUploadFn: func(context.Context, string, string, string, time.Time) (workspaceservice.WorkspaceAppUploadedFile, error) {
return workspaceservice.WorkspaceAppUploadedFile{}, workspaceservice.ErrWorkspaceAppUploadNotReady
},
},
}),
)
recorder := performGeneratedRouteRequest(
t,
mux,
http.MethodPost,
"/v1/workspaces/workspace-1/apps/canvas/uploads/upload-1/complete",
nil,
)
if recorder.Code != http.StatusBadRequest {
t.Fatalf("complete status = %d, want %d; body: %s", recorder.Code, http.StatusBadRequest, recorder.Body.String())
}
assertGeneratedRouteError(
t,
recorder,
tuttigenerated.InvalidRequest,
apierrors.ReasonMalformedRequest,
"workspace app upload content is not ready",
)
}
type stubWorkspaceAppCenterService struct {
listFn func(context.Context, string) ([]workspacebiz.WorkspaceApp, error)
installWithOptionsFn func(context.Context, string, string, workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error)
loadLocalPackageFn func(context.Context, string, string, workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error)
reloadLocalPackageFn func(context.Context, string, string, workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error)
listReferencesFn func(context.Context, string, string, workspacebiz.AppReferenceListInput) (workspacebiz.AppReferenceListResult, error)
searchReferencesFn func(context.Context, string, string, workspacebiz.AppReferenceSearchInput) (workspacebiz.AppReferenceListResult, error)
prepareWorkspaceAppUploadFn func(context.Context, string, string, workspaceservice.PrepareWorkspaceAppUploadInput) (workspaceservice.WorkspaceAppUploadSession, error)
putWorkspaceAppUploadContentFn func(context.Context, string, string, string, workspaceservice.PutWorkspaceAppUploadContentInput) error
completeWorkspaceAppUploadFn func(context.Context, string, string, string, time.Time) (workspaceservice.WorkspaceAppUploadedFile, error)
cancelWorkspaceAppUploadFn func(context.Context, string, string, string) error
}
func (stubWorkspaceAppCenterService) Add(context.Context, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (stubWorkspaceAppCenterService) DeletePackage(context.Context, string, string) error {
return nil
}
func (stubWorkspaceAppCenterService) ExportPackage(context.Context, string, string, string) (workspaceservice.AppPackageArchiveResult, error) {
return workspaceservice.AppPackageArchiveResult{}, nil
}
func (stubWorkspaceAppCenterService) ImportPackage(context.Context, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (stubWorkspaceAppCenterService) Install(context.Context, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (s stubWorkspaceAppCenterService) InstallWithOptions(ctx context.Context, workspaceID string, appID string, options workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error) {
if s.installWithOptionsFn == nil {
return workspacebiz.WorkspaceApp{}, nil
}
return s.installWithOptionsFn(ctx, workspaceID, appID, options)
}
func (stubWorkspaceAppCenterService) Launch(context.Context, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (s stubWorkspaceAppCenterService) LoadLocalPackage(ctx context.Context, workspaceID string, sourceDir string, options workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error) {
if s.loadLocalPackageFn == nil {
return workspacebiz.WorkspaceApp{}, nil
}
return s.loadLocalPackageFn(ctx, workspaceID, sourceDir, options)
}
func (s stubWorkspaceAppCenterService) ListReferences(ctx context.Context, workspaceID string, appID string, input workspacebiz.AppReferenceListInput) (workspacebiz.AppReferenceListResult, error) {
if s.listReferencesFn == nil {
return workspacebiz.AppReferenceListResult{}, nil
}
return s.listReferencesFn(ctx, workspaceID, appID, input)
}
func (s stubWorkspaceAppCenterService) SearchReferences(ctx context.Context, workspaceID string, appID string, input workspacebiz.AppReferenceSearchInput) (workspacebiz.AppReferenceListResult, error) {
if s.searchReferencesFn == nil {
return workspacebiz.AppReferenceListResult{}, nil
}
return s.searchReferencesFn(ctx, workspaceID, appID, input)
}
func (s stubWorkspaceAppCenterService) PrepareWorkspaceAppUpload(ctx context.Context, workspaceID string, appID string, input workspaceservice.PrepareWorkspaceAppUploadInput) (workspaceservice.WorkspaceAppUploadSession, error) {
if s.prepareWorkspaceAppUploadFn == nil {
return workspaceservice.WorkspaceAppUploadSession{}, nil
}
return s.prepareWorkspaceAppUploadFn(ctx, workspaceID, appID, input)
}
func (s stubWorkspaceAppCenterService) PutWorkspaceAppUploadContent(ctx context.Context, workspaceID string, appID string, uploadID string, input workspaceservice.PutWorkspaceAppUploadContentInput) error {
if s.putWorkspaceAppUploadContentFn == nil {
return nil
}
return s.putWorkspaceAppUploadContentFn(ctx, workspaceID, appID, uploadID, input)
}
func (s stubWorkspaceAppCenterService) CompleteWorkspaceAppUpload(ctx context.Context, workspaceID string, appID string, uploadID string, now time.Time) (workspaceservice.WorkspaceAppUploadedFile, error) {
if s.completeWorkspaceAppUploadFn == nil {
return workspaceservice.WorkspaceAppUploadedFile{}, nil
}
return s.completeWorkspaceAppUploadFn(ctx, workspaceID, appID, uploadID, now)
}
func (s stubWorkspaceAppCenterService) CancelWorkspaceAppUpload(ctx context.Context, workspaceID string, appID string, uploadID string) error {
if s.cancelWorkspaceAppUploadFn == nil {
return nil
}
return s.cancelWorkspaceAppUploadFn(ctx, workspaceID, appID, uploadID)
}
func (s stubWorkspaceAppCenterService) List(ctx context.Context, workspaceID string) ([]workspacebiz.WorkspaceApp, error) {
if s.listFn == nil {
return nil, nil
}
return s.listFn(ctx, workspaceID)
}
func (stubWorkspaceAppCenterService) CatalogLoadState() workspacebiz.AppCatalogLoadState {
return workspacebiz.AppCatalogLoadState{}
}
func (stubWorkspaceAppCenterService) RefreshCatalog(context.Context, string) ([]workspacebiz.WorkspaceApp, error) {
return nil, nil
}
func (stubWorkspaceAppCenterService) Remove(context.Context, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (stubWorkspaceAppCenterService) ReplaceIcon(context.Context, string, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (s stubWorkspaceAppCenterService) ReloadLocalPackage(ctx context.Context, workspaceID string, appID string, options workspaceservice.InstallOptions) (workspacebiz.WorkspaceApp, error) {
if s.reloadLocalPackageFn == nil {
return workspacebiz.WorkspaceApp{}, nil
}
return s.reloadLocalPackageFn(ctx, workspaceID, appID, options)
}
func (stubWorkspaceAppCenterService) Retry(context.Context, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (stubWorkspaceAppCenterService) Rollback(context.Context, string, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}
func (stubWorkspaceAppCenterService) StartEnabled(context.Context, string) ([]workspacebiz.WorkspaceApp, error) {
return nil, nil
}
func (stubWorkspaceAppCenterService) StopAll(context.Context, string) ([]workspacebiz.WorkspaceApp, error) {
return nil, nil
}
func (stubWorkspaceAppCenterService) Uninstall(context.Context, string, string) (workspacebiz.WorkspaceApp, error) {
return workspacebiz.WorkspaceApp{}, nil
}