github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/modules/deploy/zz_deploy_test.go (about)

     1  package deploy_test
     2  
     3  import (
     4  	"context"
     5  	"runtime"
     6  	"testing"
     7  
     8  	"github.com/DATA-DOG/go-sqlmock"
     9  	"github.com/agiledragon/gomonkey/v2"
    10  	"github.com/golang/mock/gomock"
    11  	. "github.com/onsi/gomega"
    12  	"github.com/pkg/errors"
    13  
    14  	confid "github.com/machinefi/w3bstream/pkg/depends/conf/id"
    15  	conflog "github.com/machinefi/w3bstream/pkg/depends/conf/log"
    16  	confmq "github.com/machinefi/w3bstream/pkg/depends/conf/mq"
    17  	confmqtt "github.com/machinefi/w3bstream/pkg/depends/conf/mqtt"
    18  	confredis "github.com/machinefi/w3bstream/pkg/depends/conf/redis"
    19  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/builder"
    20  	"github.com/machinefi/w3bstream/pkg/depends/x/contextx"
    21  	"github.com/machinefi/w3bstream/pkg/enums"
    22  	"github.com/machinefi/w3bstream/pkg/errors/status"
    23  	"github.com/machinefi/w3bstream/pkg/models"
    24  	"github.com/machinefi/w3bstream/pkg/modules/config"
    25  	"github.com/machinefi/w3bstream/pkg/modules/deploy"
    26  	optypes "github.com/machinefi/w3bstream/pkg/modules/operator/pool/types/mock"
    27  	wasmapi "github.com/machinefi/w3bstream/pkg/modules/vm/wasmapi/types/mock"
    28  	mock_sqlx "github.com/machinefi/w3bstream/pkg/test/mock_depends_kit_sqlx"
    29  	"github.com/machinefi/w3bstream/pkg/test/patch_models"
    30  	"github.com/machinefi/w3bstream/pkg/test/patch_modules"
    31  	"github.com/machinefi/w3bstream/pkg/types"
    32  	"github.com/machinefi/w3bstream/pkg/types/wasm"
    33  )
    34  
    35  var (
    36  	anyError    = errors.New("any")
    37  	anySFID     = types.SFID(124)
    38  	anyWasmCode = []byte("any")
    39  )
    40  
    41  func TestDeploy(t *testing.T) {
    42  	ctl := gomock.NewController(t)
    43  	defer ctl.Finish()
    44  
    45  	var (
    46  		d = &struct {
    47  			*mock_sqlx.MockDBExecutor
    48  			*mock_sqlx.MockTxExecutor
    49  		}{
    50  			MockDBExecutor: mock_sqlx.NewMockDBExecutor(ctl),
    51  			MockTxExecutor: mock_sqlx.NewMockTxExecutor(ctl),
    52  		}
    53  		idg        = confid.MustNewSFIDGenerator()
    54  		mqttBroker *confmqtt.Broker
    55  		mqttClient *confmqtt.Client
    56  	)
    57  
    58  	// mock default mqtt context
    59  	{
    60  		mqttBroker = &confmqtt.Broker{}
    61  		mqttBroker.SetDefault()
    62  
    63  		mqttClient = &confmqtt.Client{}
    64  	}
    65  
    66  	wasmApiServer := wasmapi.NewMockServer(ctl)
    67  	operatorPool := optypes.NewMockPool(ctl)
    68  
    69  	ctx := contextx.WithContextCompose(
    70  		types.WithMgrDBExecutorContext(d),
    71  		conflog.WithLoggerContext(conflog.Std()),
    72  		types.WithLoggerContext(conflog.Std()),
    73  		confid.WithSFIDGeneratorContext(idg),
    74  		types.WithAppletContext(&models.Applet{}),
    75  		types.WithResourceContext(&models.Resource{}),
    76  		types.WithInstanceContext(&models.Instance{}),
    77  		types.WithWasmDBConfigContext(&types.WasmDBConfig{}),
    78  		types.WithRedisEndpointContext(&confredis.Redis{}),
    79  		confmq.WithMqContext(&confmq.Config{}),
    80  		types.WithMqttBrokerContext(mqttBroker),
    81  		types.WithETHClientConfigContext(&types.ETHClientConfig{}),
    82  		types.WithChainConfigContext(&types.ChainConfig{}),
    83  		wasm.WithMQTTClientContext(mqttClient),
    84  		types.WithWasmApiServerContext(wasmApiServer),
    85  		types.WithOperatorPoolContext(operatorPool),
    86  	)(context.Background())
    87  
    88  	d.MockDBExecutor.EXPECT().T(gomock.Any()).Return(&builder.Table{}).AnyTimes()
    89  	d.MockTxExecutor.EXPECT().IsTx().Return(true).AnyTimes()
    90  	d.MockDBExecutor.EXPECT().Context().Return(ctx).AnyTimes()
    91  
    92  	errFrom := func(from string) error {
    93  		return errors.New(from)
    94  	}
    95  
    96  	t.Run("#Init", func(t *testing.T) {
    97  		if runtime.GOOS == `darwin` {
    98  			return
    99  		}
   100  
   101  		patch := gomonkey.NewPatches()
   102  		defer patch.Reset()
   103  
   104  		t.Run("#Failed", func(t *testing.T) {
   105  			t.Run("#ListInstanceFailed", func(t *testing.T) {
   106  				from := "models.Instance.List"
   107  				patch = patch_models.InstanceList(patch, nil, errFrom(from))
   108  				NewWithT(t).Expect(deploy.Init(ctx).Error()).To(Equal(from))
   109  			})
   110  
   111  			patch = patch_models.InstanceList(patch, []models.Instance{{
   112  				InstanceInfo: models.InstanceInfo{State: enums.INSTANCE_STATE__STARTED},
   113  			}}, nil)
   114  
   115  			t.Run("#FetchAppletFailed", func(t *testing.T) {
   116  				from := "models.Applet.FetchByAppletID"
   117  				patch = patch_models.AppletFetchByAppletID(patch, nil, errFrom(from))
   118  				NewWithT(t).Expect(deploy.Init(ctx)).To(BeNil())
   119  			})
   120  
   121  			patch = patch_models.AppletFetchByAppletID(patch, &models.Applet{}, nil)
   122  
   123  			t.Run("#FetchResourceFailed", func(t *testing.T) {
   124  				from := "resource.GetContentBySFID"
   125  				patch = patch_modules.ResourceGetContentBySFID(patch, nil, nil, errFrom(from))
   126  				NewWithT(t).Expect(deploy.Init(ctx)).To(BeNil())
   127  			})
   128  
   129  			patch = patch_modules.ResourceGetContentBySFID(patch, &models.Resource{}, anyWasmCode, nil)
   130  
   131  			t.Run("#UpsertInstanceFailed", func(t *testing.T) {
   132  				from := "deploy.UpsertByCode"
   133  				patch = patch_modules.DeployUpsertByCode(patch, nil, errFrom(from))
   134  				NewWithT(t).Expect(deploy.Init(ctx)).To(BeNil())
   135  			})
   136  
   137  			t.Run("#UnexpectedDeployedVMState", func(t *testing.T) {
   138  				ins := &models.Instance{}
   139  				patch = patch_modules.DeployUpsertByCode(patch, ins, nil)
   140  				NewWithT(t).Expect(deploy.Init(ctx)).To(BeNil())
   141  			})
   142  		})
   143  		t.Run("#Success", func(t *testing.T) {
   144  			ins := &models.Instance{
   145  				InstanceInfo: models.InstanceInfo{State: enums.INSTANCE_STATE__STARTED},
   146  			}
   147  			patch = patch_modules.DeployUpsertByCode(patch, ins, nil)
   148  			NewWithT(t).Expect(deploy.Init(ctx)).To(BeNil())
   149  		})
   150  	})
   151  
   152  	t.Run("#GetBySFID", func(t *testing.T) {
   153  		if runtime.GOOS == `darwin` {
   154  			return
   155  		}
   156  		patch := gomonkey.NewPatches()
   157  		defer patch.Reset()
   158  
   159  		t.Run("#Failed", func(t *testing.T) {
   160  			t.Run("#InstanceNotFound", func(t *testing.T) {
   161  				patch = patch_models.InstanceFetchByInstanceID(patch, nil, mock_sqlx.ErrNotFound)
   162  				_, err := deploy.GetBySFID(ctx, anySFID)
   163  				mock_sqlx.ExpectError(t, err, status.InstanceNotFound)
   164  			})
   165  			t.Run("#DatabaseError", func(t *testing.T) {
   166  				from := "models.Instance.FetchByInstanceID"
   167  				patch = patch_models.InstanceFetchByInstanceID(patch, nil, errFrom(from))
   168  				_, err := deploy.GetBySFID(ctx, anySFID)
   169  				mock_sqlx.ExpectError(t, err, status.DatabaseError, from)
   170  			})
   171  		})
   172  
   173  		t.Run("#Success", func(t *testing.T) {
   174  			patch = patch_models.InstanceFetchByInstanceID(patch, &models.Instance{}, nil)
   175  			_, err := deploy.GetBySFID(ctx, anySFID)
   176  			NewWithT(t).Expect(err).To(BeNil())
   177  		})
   178  	})
   179  
   180  	t.Run("#GetByAppletSFID", func(t *testing.T) {
   181  		if runtime.GOOS == `darwin` {
   182  			return
   183  		}
   184  		patch := gomonkey.NewPatches()
   185  		defer patch.Reset()
   186  
   187  		t.Run("#Failed", func(t *testing.T) {
   188  			t.Run("#InstanceNotFound", func(t *testing.T) {
   189  				patch = patch_models.InstanceFetchByAppletID(patch, nil, mock_sqlx.ErrNotFound)
   190  				_, err := deploy.GetByAppletSFID(ctx, anySFID)
   191  				mock_sqlx.ExpectError(t, err, status.InstanceNotFound)
   192  			})
   193  			t.Run("#DatabaseError", func(t *testing.T) {
   194  				from := "models.Instance.FetchByAppletID"
   195  				patch = patch_models.InstanceFetchByAppletID(patch, nil, errFrom(from))
   196  				_, err := deploy.GetByAppletSFID(ctx, anySFID)
   197  				mock_sqlx.ExpectError(t, err, status.DatabaseError, from)
   198  			})
   199  		})
   200  
   201  		t.Run("#Success", func(t *testing.T) {
   202  			patch = patch_models.InstanceFetchByAppletID(patch, &models.Instance{}, nil)
   203  			_, err := deploy.GetByAppletSFID(ctx, anySFID)
   204  			NewWithT(t).Expect(err).To(BeNil())
   205  		})
   206  	})
   207  
   208  	t.Run("#List", func(t *testing.T) {
   209  		r := &deploy.ListReq{}
   210  		t.Run("#Failed", func(t *testing.T) {
   211  			from := "ListError"
   212  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(errFrom(from)).Times(1)
   213  			_, err := deploy.List(ctx, r)
   214  			mock_sqlx.ExpectError(t, err, status.DatabaseError, from)
   215  
   216  			from = "CountError"
   217  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(1)
   218  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(errFrom(from)).Times(1)
   219  			r.ProjectID = 1000
   220  			_, err = deploy.List(ctx, r)
   221  			mock_sqlx.ExpectError(t, err, status.DatabaseError, from)
   222  		})
   223  		t.Run("#Success", func(t *testing.T) {
   224  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(2)
   225  			_, err := deploy.List(ctx, &deploy.ListReq{})
   226  			NewWithT(t).Expect(err).To(BeNil())
   227  		})
   228  	})
   229  
   230  	t.Run("#ListByCond", func(t *testing.T) {
   231  		r := &deploy.CondArgs{ProjectID: 1000}
   232  		t.Run("#Failed", func(t *testing.T) {
   233  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrDatabase).Times(1)
   234  			_, err := deploy.ListByCond(ctx, r)
   235  			mock_sqlx.ExpectError(t, err, status.DatabaseError)
   236  		})
   237  		t.Run("#Success", func(t *testing.T) {
   238  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(1)
   239  			_, err := deploy.ListByCond(ctx, r)
   240  			NewWithT(t).Expect(err).To(BeNil())
   241  		})
   242  	})
   243  
   244  	t.Run("#RemoveBySFID", func(t *testing.T) {
   245  		if runtime.GOOS == `darwin` {
   246  			return
   247  		}
   248  		patch := gomonkey.NewPatches()
   249  		defer patch.Reset()
   250  
   251  		t.Run("#Failed", func(t *testing.T) {
   252  			t.Run("#TxDeleteByInstanceIDFailed", func(t *testing.T) {
   253  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrDatabase).Times(1)
   254  				err := deploy.RemoveBySFID(ctx, anySFID)
   255  				mock_sqlx.ExpectError(t, err, status.DatabaseError)
   256  			})
   257  
   258  			t.Run("#TxConfigRemoveFailed", func(t *testing.T) {
   259  				from := "config.Remove"
   260  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   261  				patch = patch_modules.ConfigRemove(patch, errFrom(from))
   262  				err := deploy.RemoveBySFID(ctx, anySFID)
   263  				NewWithT(t).Expect(err.Error()).To(Equal(from))
   264  			})
   265  
   266  			patch = patch_modules.ConfigRemove(patch, nil)
   267  
   268  			t.Run("#TxWasmLogRemoveFailed", func(t *testing.T) {
   269  				from := "wasmlog.Remove"
   270  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   271  				patch = patch_modules.WasmLogRemove(patch, errFrom(from))
   272  				err := deploy.RemoveBySFID(ctx, anySFID)
   273  				NewWithT(t).Expect(err.Error()).To(Equal(from))
   274  			})
   275  		})
   276  		t.Run("#Success", func(t *testing.T) {
   277  			d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   278  			patch = patch_modules.WasmLogRemove(patch, nil)
   279  			err := deploy.RemoveBySFID(ctx, anySFID)
   280  			NewWithT(t).Expect(err).To(BeNil())
   281  		})
   282  	})
   283  
   284  	t.Run("#RemoveByAppletSFID", func(t *testing.T) {
   285  		if runtime.GOOS == `darwin` {
   286  			return
   287  		}
   288  		patch := gomonkey.NewPatches()
   289  		defer patch.Reset()
   290  
   291  		t.Run("#Failed", func(t *testing.T) {
   292  			t.Run("#TxDeployGetByAppletSFIDFailed", func(t *testing.T) {
   293  				from := "deploy.GetByAppletSFID"
   294  				patch = patch_modules.DeployGetByAppletSFID(patch, nil, errFrom(from))
   295  				NewWithT(t).Expect(deploy.RemoveByAppletSFID(ctx, anySFID).Error()).To(Equal(from))
   296  			})
   297  
   298  			patch = patch_modules.DeployGetByAppletSFID(patch, &models.Instance{}, nil)
   299  
   300  			t.Run("#TxDeployRemoveBySFIDFailed", func(t *testing.T) {
   301  				from := "deploy.RemoveBySFID"
   302  				patch = patch_modules.DeployRemoveBySFID(patch, errFrom(from))
   303  				NewWithT(t).Expect(deploy.RemoveByAppletSFID(ctx, anySFID).Error()).To(Equal(from))
   304  			})
   305  		})
   306  
   307  		t.Run("#Success", func(t *testing.T) {
   308  			patch = patch_modules.DeployRemoveBySFID(patch, nil)
   309  			NewWithT(t).Expect(deploy.RemoveByAppletSFID(ctx, anySFID)).To(BeNil())
   310  		})
   311  	})
   312  
   313  	t.Run("#Remove", func(t *testing.T) {
   314  		if runtime.GOOS == `darwin` {
   315  			return
   316  		}
   317  		patch := gomonkey.NewPatches()
   318  		defer patch.Reset()
   319  
   320  		r := &deploy.CondArgs{}
   321  		t.Run("#Failed", func(t *testing.T) {
   322  			t.Run("#TxDeployListByCondFailed", func(t *testing.T) {
   323  				from := "deploy.ListByCond"
   324  				patch = patch_modules.DeployListByCond(patch, nil, errFrom(from))
   325  				NewWithT(t).Expect(deploy.Remove(ctx, r).Error()).To(Equal(from))
   326  			})
   327  
   328  			patch = patch_modules.DeployListByCond(patch, []models.Instance{{}}, nil)
   329  
   330  			t.Run("#TxDeployRemoveBySFIDFailed", func(t *testing.T) {
   331  				from := "deploy.RemoveBySFID"
   332  				patch = patch_modules.DeployRemoveBySFID(patch, errFrom(from))
   333  				NewWithT(t).Expect(deploy.Remove(ctx, r).Error()).To(Equal(from))
   334  			})
   335  		})
   336  		t.Run("#Success", func(t *testing.T) {
   337  			patch = patch_modules.DeployRemoveBySFID(patch, nil)
   338  			NewWithT(t).Expect(deploy.Remove(ctx, r)).To(BeNil())
   339  		})
   340  	})
   341  
   342  	t.Run("#UpsertByCode", func(t *testing.T) {
   343  		if runtime.GOOS == `darwin` {
   344  			return
   345  		}
   346  		patch := gomonkey.NewPatches()
   347  		defer patch.Reset()
   348  
   349  		updateCasePatch := func(overwrite *models.Instance) {
   350  			patch = patch_models.InstanceFetchByAppletID(patch, overwrite, nil)
   351  		}
   352  		createCasePatch := func() {
   353  			patch = patch_models.InstanceFetchByAppletID(patch, nil, mock_sqlx.ErrNotFound)
   354  		}
   355  
   356  		req := &deploy.CreateReq{}
   357  		code := []byte("any")
   358  		state := enums.INSTANCE_STATE__STARTED
   359  
   360  		t.Run("#Failed", func(t *testing.T) {
   361  			t.Run("#InvalidInstanceState", func(t *testing.T) {
   362  				_, err := deploy.UpsertByCode(ctx, req, code, enums.InstanceState(0))
   363  				mock_sqlx.ExpectError(t, err, status.InvalidVMState)
   364  			})
   365  			t.Run("#TxFetchByAppletIDFailed", func(t *testing.T) {
   366  				t.Run("#DatabaseError", func(t *testing.T) {
   367  					from := "models.Instance.FetchByAppletID"
   368  					patch = patch_models.InstanceFetchByAppletID(patch, nil, errFrom(from))
   369  					_, err := deploy.UpsertByCode(ctx, req, code, state)
   370  					mock_sqlx.ExpectError(t, err, status.DatabaseError, from)
   371  				})
   372  				t.Run("#InvalidAppletContext", func(t *testing.T) {
   373  					updateCasePatch(&models.Instance{
   374  						RelInstance: models.RelInstance{InstanceID: anySFID + 1},
   375  					})
   376  					_, err := deploy.UpsertByCode(ctx, req, code, state, anySFID)
   377  					mock_sqlx.ExpectError(t, err, status.InvalidAppletContext)
   378  				})
   379  			})
   380  			t.Run("#TxUpdateOrCreateInstanceFailed", func(t *testing.T) {
   381  				t.Run("#CaseUpdateFailed", func(t *testing.T) {
   382  					updateCasePatch(&models.Instance{
   383  						RelInstance: models.RelInstance{InstanceID: anySFID},
   384  					})
   385  					t.Run("#MultiInstanceDeployed", func(t *testing.T) {
   386  						patch = patch_models.InstanceUpdateByInstanceID(patch, nil, mock_sqlx.ErrConflict)
   387  						_, err := deploy.UpsertByCode(ctx, req, code, state, anySFID)
   388  						mock_sqlx.ExpectError(t, err, status.MultiInstanceDeployed)
   389  					})
   390  					t.Run("#DatabaseError", func(t *testing.T) {
   391  						from := "models.Instance.UpdateByInstanceID"
   392  						patch = patch_models.InstanceUpdateByInstanceID(patch, nil, errFrom(from))
   393  						_, err := deploy.UpsertByCode(ctx, req, code, state, anySFID)
   394  						mock_sqlx.ExpectError(t, err, status.DatabaseError, from)
   395  					})
   396  				})
   397  				t.Run("#CaseCreateFailed", func(t *testing.T) {
   398  					createCasePatch()
   399  					t.Run("#MultiInstanceDeployed", func(t *testing.T) {
   400  						patch = patch_models.InstanceCreate(patch, nil, mock_sqlx.ErrConflict)
   401  						_, err := deploy.UpsertByCode(ctx, req, code, state, anySFID)
   402  						mock_sqlx.ExpectError(t, err, status.MultiInstanceDeployed)
   403  					})
   404  					t.Run("#DatabaseError", func(t *testing.T) {
   405  						patch = patch_models.InstanceCreate(patch, nil, mock_sqlx.ErrDatabase)
   406  						_, err := deploy.UpsertByCode(ctx, req, code, state, anySFID)
   407  						mock_sqlx.ExpectError(t, err, status.DatabaseError)
   408  					})
   409  				})
   410  
   411  				ins := &models.Instance{RelInstance: models.RelInstance{InstanceID: anySFID}}
   412  				patch = patch_models.InstanceUpdateByInstanceID(patch, ins, nil)
   413  				patch = patch_models.InstanceCreate(patch, ins, nil)
   414  			})
   415  
   416  			t.Run("#TxUpdateConfigFailed", func(t *testing.T) {
   417  				req.Cache = &wasm.Cache{}
   418  
   419  				t.Run("#ConfigRemoveFailed", func(t *testing.T) {
   420  					from := "config.Remove"
   421  					patch = patch_modules.ConfigRemove(patch, errFrom(from))
   422  					_, err := deploy.UpsertByCode(ctx, req, code, state)
   423  					NewWithT(t).Expect(err.Error()).To(Equal(from))
   424  				})
   425  
   426  				patch = patch_modules.ConfigRemove(patch, nil)
   427  
   428  				t.Run("#ConfigCreateFailed", func(t *testing.T) {
   429  					from := "config.Create"
   430  					patch = patch_modules.ConfigCreate(patch, nil, errFrom(from))
   431  					_, err := deploy.UpsertByCode(ctx, req, code, state)
   432  					NewWithT(t).Expect(err.Error()).To(Equal(from))
   433  				})
   434  
   435  				patch = patch_modules.ConfigCreate(patch, nil, nil)
   436  			})
   437  
   438  			t.Run("#TxCreateInstanceVM", func(t *testing.T) {
   439  				updateCasePatch(&models.Instance{})
   440  				t.Run("#WihtInstanceRuntimeContextFailed", func(t *testing.T) {
   441  					from := "deploy.WithInstanceRuntimeContext"
   442  					patch = patch_modules.DeployWithInstanceRuntimeContext(patch, nil, errFrom(from))
   443  					_, err := deploy.UpsertByCode(ctx, req, code, state)
   444  					NewWithT(t).Expect(err.Error()).To(Equal(from))
   445  				})
   446  				patch = patch_modules.DeployWithInstanceRuntimeContext(patch, nil, nil)
   447  				t.Run("#VmNewInstanceFailed", func(t *testing.T) {
   448  					from := "vm.NewInstance"
   449  					patch = patch_modules.VmNewInstance(patch, errFrom(from))
   450  					_, err := deploy.UpsertByCode(ctx, req, code, state)
   451  					mock_sqlx.ExpectError(t, err, status.CreateInstanceFailed, from)
   452  				})
   453  			})
   454  		})
   455  
   456  		t.Run("#Success", func(t *testing.T) {
   457  			patch = patch_modules.VmNewInstance(patch, nil)
   458  			_, err := deploy.UpsertByCode(ctx, req, code, state)
   459  			NewWithT(t).Expect(err).To(BeNil())
   460  		})
   461  	})
   462  
   463  	t.Run("#Upsert", func(t *testing.T) {
   464  		if runtime.GOOS == `darwin` {
   465  			return
   466  		}
   467  		patch := gomonkey.NewPatches()
   468  		defer patch.Reset()
   469  
   470  		req := &deploy.CreateReq{}
   471  		state := enums.INSTANCE_STATE__STARTED
   472  
   473  		t.Run("#Failed", func(t *testing.T) {
   474  			from := "resource.GetContentBySFID"
   475  			patch = patch_modules.ResourceGetContentBySFID(patch, nil, nil, errFrom(from))
   476  			_, err := deploy.Upsert(ctx, req, state)
   477  			NewWithT(t).Expect(err.Error()).To(Equal(from))
   478  		})
   479  		from := "deploy.UpsertByCode"
   480  		patch = patch_modules.ResourceGetContentBySFID(patch, nil, nil, nil)
   481  		patch = patch_modules.DeployUpsertByCode(patch, nil, errFrom(from))
   482  		_, err := deploy.Upsert(ctx, req, state)
   483  		NewWithT(t).Expect(err.Error()).To(Equal(from))
   484  	})
   485  
   486  	t.Run("#Deploy", func(t *testing.T) {
   487  		patch := gomonkey.NewPatches()
   488  		defer patch.Reset()
   489  
   490  		t.Run("#Failed", func(t *testing.T) {
   491  			t.Run("#UnknownDeployCmd", func(t *testing.T) {
   492  				err := deploy.Deploy(ctx, enums.DeployCmd(100))
   493  				mock_sqlx.ExpectError(t, err, status.UnknownDeployCommand, "100")
   494  			})
   495  
   496  			t.Run("#TxUpdateInstanceFailed", func(t *testing.T) {
   497  				t.Run("#MultiInstanceDeployed", func(t *testing.T) {
   498  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrConflict).Times(1)
   499  					err := deploy.Deploy(ctx, enums.DEPLOY_CMD__HUNGUP)
   500  					mock_sqlx.ExpectError(t, err, status.MultiInstanceDeployed)
   501  				})
   502  				t.Run("#InstanceNotFound", func(t *testing.T) {
   503  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrNotFound).Times(1)
   504  					err := deploy.Deploy(ctx, enums.DEPLOY_CMD__HUNGUP)
   505  					mock_sqlx.ExpectError(t, err, status.InstanceNotFound)
   506  				})
   507  				t.Run("#DatabaseError", func(t *testing.T) {
   508  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrDatabase).Times(1)
   509  					err := deploy.Deploy(ctx, enums.DEPLOY_CMD__HUNGUP)
   510  					mock_sqlx.ExpectError(t, err, status.DatabaseError)
   511  				})
   512  			})
   513  		})
   514  		d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(sqlmock.NewResult(1, 1), nil).Times(2)
   515  		err := deploy.Deploy(ctx, enums.DEPLOY_CMD__HUNGUP)
   516  		NewWithT(t).Expect(err).To(BeNil())
   517  
   518  		err = deploy.Deploy(ctx, enums.DEPLOY_CMD__START)
   519  		NewWithT(t).Expect(err).To(BeNil())
   520  	})
   521  
   522  	t.Run("#WithInstanceRuntimeContext", func(t *testing.T) {
   523  		if runtime.GOOS == `darwin` {
   524  			return
   525  		}
   526  		patch := gomonkey.NewPatches()
   527  		defer patch.Reset()
   528  
   529  		t.Run("#Failed", func(t *testing.T) {
   530  			t.Run("#FetchProjectFailed", func(t *testing.T) {
   531  				patch = patch_models.ProjectFetchByProjectID(patch, nil, errFrom(t.Name()))
   532  				_, err := deploy.WithInstanceRuntimeContext(ctx)
   533  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   534  			})
   535  
   536  			patch = patch_models.ProjectFetchByProjectID(patch, &models.Project{}, nil)
   537  
   538  			t.Run("#GetProjectOperatorFailed", func(t *testing.T) {
   539  				patch = patch_modules.ProjectOperatorGetByProject(patch, nil, errFrom(t.Name()))
   540  				_, err := deploy.WithInstanceRuntimeContext(ctx)
   541  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   542  			})
   543  
   544  			patch = patch_modules.ProjectOperatorGetByProject(patch, &models.ProjectOperator{}, nil)
   545  
   546  			t.Run("#ListAccountOperatorsFailed", func(t *testing.T) {
   547  				patch = patch_modules.OperatorListByCond(patch, nil, errFrom(t.Name()))
   548  				_, err := deploy.WithInstanceRuntimeContext(ctx)
   549  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   550  			})
   551  
   552  			patch = patch_modules.OperatorListByCond(patch, []models.Operator{{}}, nil)
   553  
   554  			t.Run("#ListConfigurationsFailed", func(t *testing.T) {
   555  				patch = patch_modules.ConfigList(patch, nil, errFrom(t.Name()))
   556  				_, err := deploy.WithInstanceRuntimeContext(ctx)
   557  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   558  			})
   559  
   560  			patch = patch_modules.ConfigList(patch, []*config.Detail{{Configuration: &wasm.Cache{}}}, nil)
   561  
   562  			t.Run("#ConfigurationsInitFailed", func(t *testing.T) {
   563  				patch_modules.TypesWasmInitConfiguration(patch, errFrom(t.Name()))
   564  				_, err := deploy.WithInstanceRuntimeContext(ctx)
   565  				mock_sqlx.ExpectError(t, err, status.ConfigInitFailed)
   566  			})
   567  
   568  			patch = patch_modules.TypesWasmInitConfiguration(patch, nil)
   569  
   570  			t.Run("#GlobalConfigurationInitFailed", func(t *testing.T) {
   571  				patch_modules.TypesWasmInitGlobalConfiguration(patch, errFrom(t.Name()))
   572  				_, err := deploy.WithInstanceRuntimeContext(ctx)
   573  				mock_sqlx.ExpectError(t, err, status.ConfigInitFailed)
   574  			})
   575  		})
   576  
   577  		t.Run("#Success", func(t *testing.T) {
   578  			patch = patch_modules.TypesWasmInitGlobalConfiguration(patch, nil)
   579  			_, err := deploy.WithInstanceRuntimeContext(ctx)
   580  			NewWithT(t).Expect(err).To(BeNil())
   581  		})
   582  	})
   583  }
   584  
   585  func TestCondArgs_Condition(t *testing.T) {
   586  	cases := []*deploy.CondArgs{
   587  		{ProjectID: 0},
   588  		{InstanceIDs: []types.SFID{1}},
   589  		{InstanceIDs: []types.SFID{1, 2}},
   590  		{AppletIDs: []types.SFID{1}},
   591  		{AppletIDs: []types.SFID{1, 2}},
   592  		{States: []enums.InstanceState{1}},
   593  		{States: []enums.InstanceState{1, 2}},
   594  	}
   595  
   596  	for _, c := range cases {
   597  		t.Log(builder.ResolveExpr(c.Condition()).Query())
   598  	}
   599  }