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

     1  package applet_test
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"runtime"
     8  	"testing"
     9  
    10  	"github.com/DATA-DOG/go-sqlmock"
    11  	"github.com/agiledragon/gomonkey/v2"
    12  	"github.com/golang/mock/gomock"
    13  	. "github.com/onsi/gomega"
    14  
    15  	confid "github.com/machinefi/w3bstream/pkg/depends/conf/id"
    16  	conflog "github.com/machinefi/w3bstream/pkg/depends/conf/log"
    17  	"github.com/machinefi/w3bstream/pkg/depends/kit/httptransport/transformer"
    18  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/builder"
    19  	"github.com/machinefi/w3bstream/pkg/depends/x/contextx"
    20  	"github.com/machinefi/w3bstream/pkg/errors/status"
    21  	"github.com/machinefi/w3bstream/pkg/models"
    22  	"github.com/machinefi/w3bstream/pkg/modules/applet"
    23  	mock_sqlx "github.com/machinefi/w3bstream/pkg/test/mock_depends_kit_sqlx"
    24  	"github.com/machinefi/w3bstream/pkg/test/patch_models"
    25  	"github.com/machinefi/w3bstream/pkg/test/patch_modules"
    26  	"github.com/machinefi/w3bstream/pkg/types"
    27  	"github.com/machinefi/w3bstream/pkg/types/wasm"
    28  )
    29  
    30  func TestCondArgs_Condition(t *testing.T) {
    31  	expr := (&applet.CondArgs{}).Condition()
    32  	NewWithT(t).Expect(expr.IsNil()).To(BeTrue())
    33  
    34  	ex := builder.ResolveExpr(
    35  		(&applet.CondArgs{
    36  			ProjectID: 100,
    37  			AppletIDs: types.SFIDs{100},
    38  			Names:     []string{"test_cond"},
    39  			NameLike:  "test_cond",
    40  			LNameLike: "test_cond",
    41  		}).Condition(),
    42  	)
    43  	NewWithT(t).Expect(len(ex.Args())).To(Equal(5))
    44  	t.Log(ex.Query(), ex.Args())
    45  }
    46  
    47  func TestCreateReq_BuildStrategies(t *testing.T) {
    48  	ctx := contextx.WithContextCompose(
    49  		conflog.WithLoggerContext(conflog.Std()),
    50  		confid.WithSFIDGeneratorContext(confid.MustNewSFIDGenerator()),
    51  		types.WithAppletContext(&models.Applet{}),
    52  		types.WithProjectContext(&models.Project{}),
    53  	)(context.Background())
    54  
    55  	r := &applet.CreateReq{
    56  		File: nil,
    57  		Info: applet.Info{},
    58  	}
    59  
    60  	// len(r.Strategies) == 0 build with default strategy info
    61  	strategies := r.BuildStrategies(ctx)
    62  	NewWithT(t).Expect(len(strategies)).To(Equal(1))
    63  
    64  	// len(r.Strategies) == 0 build with input strategy info
    65  	r.Info.Strategies = append(r.Info.Strategies, models.StrategyInfo{})
    66  	strategies = r.BuildStrategies(ctx)
    67  	NewWithT(t).Expect(len(strategies)).To(Equal(len(r.Info.Strategies)))
    68  }
    69  
    70  func TestApplet(t *testing.T) {
    71  	c := gomock.NewController(t)
    72  	defer c.Finish()
    73  
    74  	d := &struct {
    75  		*mock_sqlx.MockDBExecutor
    76  		*mock_sqlx.MockTxExecutor
    77  	}{
    78  		MockDBExecutor: mock_sqlx.NewMockDBExecutor(c),
    79  		MockTxExecutor: mock_sqlx.NewMockTxExecutor(c),
    80  	}
    81  	idg := confid.MustNewSFIDGenerator()
    82  	ctx := contextx.WithContextCompose(
    83  		types.WithMgrDBExecutorContext(d),
    84  		conflog.WithLoggerContext(conflog.Std()),
    85  		confid.WithSFIDGeneratorContext(idg),
    86  		types.WithProjectContext(&models.Project{}),
    87  		types.WithAccountContext(&models.Account{}),
    88  		types.WithAppletContext(&models.Applet{}),
    89  	)(context.Background())
    90  
    91  	d.MockDBExecutor.EXPECT().T(gomock.Any()).Return(&builder.Table{}).AnyTimes()
    92  	d.MockDBExecutor.EXPECT().Context().Return(ctx).AnyTimes()
    93  	d.MockTxExecutor.EXPECT().IsTx().Return(true).AnyTimes()
    94  
    95  	t.Run("GetBySFID", func(t *testing.T) {
    96  		t.Run("#Failed", func(t *testing.T) {
    97  			t.Run("#AppletNotFound", func(t *testing.T) {
    98  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
    99  
   100  				_, err := applet.GetBySFID(ctx, idg.MustGenSFID())
   101  				mock_sqlx.ExpectError(t, err, status.AppletNotFound)
   102  			})
   103  			t.Run("#DatabaseError", func(t *testing.T) {
   104  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrDatabase).Times(1)
   105  
   106  				_, err := applet.GetBySFID(ctx, idg.MustGenSFID())
   107  				mock_sqlx.ExpectError(t, err, status.DatabaseError)
   108  			})
   109  		})
   110  
   111  		t.Run("#Success", func(t *testing.T) {
   112  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(1)
   113  
   114  			_, err := applet.GetBySFID(ctx, idg.MustGenSFID())
   115  			NewWithT(t).Expect(err).To(BeNil())
   116  		})
   117  	})
   118  
   119  	cause := func(msg string) error { return errors.New(msg) }
   120  
   121  	t.Run("RemoveBySFID", func(t *testing.T) {
   122  		t.Run("#Failed", func(t *testing.T) {
   123  			t.Run("#DeleteByAppletIDFailed", func(t *testing.T) {
   124  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, cause(t.Name())).Times(1)
   125  				err := applet.RemoveBySFID(ctx, 100)
   126  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   127  			})
   128  			t.Run("RemoveStrategyFailed", func(t *testing.T) {
   129  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   130  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, cause(t.Name())).Times(1)
   131  				err := applet.RemoveBySFID(ctx, 100)
   132  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   133  			})
   134  			t.Run("#RemoveInstanceFailed", func(t *testing.T) {
   135  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(2)
   136  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(cause(t.Name())).Times(1)
   137  				err := applet.RemoveBySFID(ctx, idg.MustGenSFID())
   138  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   139  			})
   140  		})
   141  
   142  		t.Run("#Success", func(t *testing.T) {
   143  			if runtime.GOOS == `darwin` {
   144  				return
   145  			}
   146  			patch := gomonkey.NewPatches()
   147  			defer patch.Reset()
   148  
   149  			d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(2)
   150  			patch = patch_modules.DeployRemoveByAppletSFID(patch, nil)
   151  
   152  			err := applet.RemoveBySFID(ctx, idg.MustGenSFID())
   153  			NewWithT(t).Expect(err).To(BeNil())
   154  		})
   155  	})
   156  
   157  	t.Run("Remove", func(t *testing.T) {
   158  		patch := gomonkey.NewPatches()
   159  		defer patch.Reset()
   160  
   161  		req := &applet.CondArgs{}
   162  		t.Run("#Failed", func(t *testing.T) {
   163  			t.Run("#ListAppletFailed", func(t *testing.T) {
   164  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(cause(t.Name())).Times(1)
   165  				err := applet.Remove(ctx, req)
   166  				mock_sqlx.ExpectError(t, err, status.DatabaseError)
   167  			})
   168  			t.Run("#BatchRemoveAppletFailed", func(t *testing.T) {
   169  				if runtime.GOOS == `darwin` {
   170  					return
   171  				}
   172  
   173  				patch = patch_models.AppletList(patch, []models.Applet{{}}, nil)
   174  				patch = patch_modules.AppletRemoveBySFID(patch, cause(t.Name()))
   175  
   176  				err := applet.Remove(ctx, req)
   177  				mock_sqlx.ExpectError(t, err, status.BatchRemoveAppletFailed)
   178  			})
   179  		})
   180  		t.Run("#Success", func(t *testing.T) {
   181  			if runtime.GOOS == `darwin` {
   182  				return
   183  			}
   184  			patch = patch_models.AppletList(patch, nil, nil)
   185  
   186  			err := applet.Remove(ctx, req)
   187  			NewWithT(t).Expect(err).To(BeNil())
   188  		})
   189  	})
   190  
   191  	t.Run("List", func(t *testing.T) {
   192  		req := &applet.ListReq{}
   193  		t.Run("#Failed", func(t *testing.T) {
   194  			t.Run("#ListFailed", func(t *testing.T) {
   195  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(cause(t.Name())).Times(1)
   196  				_, err := applet.List(ctx, req)
   197  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   198  			})
   199  			t.Run("#CountFailed", func(t *testing.T) {
   200  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(1)
   201  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(cause(t.Name())).Times(1)
   202  				_, err := applet.List(ctx, req)
   203  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   204  			})
   205  		})
   206  		t.Run("#Success", func(t *testing.T) {
   207  			d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(2)
   208  			_, err := applet.List(ctx, req)
   209  			NewWithT(t).Expect(err).To(BeNil())
   210  		})
   211  	})
   212  
   213  	t.Run("ListDetail", func(t *testing.T) {
   214  		patch := gomonkey.NewPatches()
   215  		defer patch.Reset()
   216  
   217  		req := &applet.ListReq{}
   218  		t.Run("#Failed", func(t *testing.T) {
   219  			t.Run("#AppletListFailed", func(t *testing.T) {
   220  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(cause(t.Name())).Times(1)
   221  				_, err := applet.ListDetail(ctx, req)
   222  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   223  			})
   224  
   225  			t.Run("#AppendDetailFailed", func(t *testing.T) {
   226  				if runtime.GOOS == `darwin` {
   227  					return
   228  				}
   229  				patch = patch_modules.AppletList(patch, &applet.ListRsp{
   230  					Data:  []models.Applet{{}},
   231  					Total: 1,
   232  				}, nil)
   233  				patch = patch_modules.DeployGetByAppletSFID(patch, &models.Instance{}, nil)
   234  				patch = patch_modules.ResourceGetBySFID(patch, nil, cause(t.Name()+"#1"))
   235  
   236  				_, err := applet.ListDetail(ctx, req)
   237  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name() + "#1"))
   238  
   239  				patch = patch_modules.DeployGetByAppletSFID(patch, nil, cause(t.Name()))
   240  				_, err = applet.ListDetail(ctx, req)
   241  				NewWithT(t).Expect(err).To(BeNil())
   242  			})
   243  		})
   244  
   245  		t.Run("#Success", func(t *testing.T) {
   246  			if runtime.GOOS == `darwin` {
   247  				return
   248  			}
   249  			patch = patch_modules.DeployGetByAppletSFID(patch, &models.Instance{}, nil)
   250  			patch = patch_modules.ResourceGetBySFID(patch, &models.Resource{}, nil)
   251  			_, err := applet.ListDetail(ctx, req)
   252  			NewWithT(t).Expect(err).To(BeNil())
   253  		})
   254  	})
   255  
   256  	t.Run("Create", func(t *testing.T) {
   257  		if runtime.GOOS == `darwin` {
   258  			return
   259  		}
   260  
   261  		patch := gomonkey.NewPatches()
   262  		defer patch.Reset()
   263  
   264  		var (
   265  			req  = &applet.CreateReq{}
   266  			code = []byte("any")
   267  		)
   268  		t.Run("#Failed", func(t *testing.T) {
   269  			t.Run("#CreateResourceFailed", func(t *testing.T) {
   270  				patch = patch_modules.ResourceCreate(patch, nil, nil, cause(t.Name()))
   271  				_, err := applet.Create(ctx, req)
   272  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   273  			})
   274  
   275  			patch = patch_modules.ResourceCreate(patch, &models.Resource{}, code, nil)
   276  
   277  			t.Run("#CreateAppletFailed", func(t *testing.T) {
   278  				t.Run("#AppletNameConflict", func(t *testing.T) {
   279  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrConflict).Times(1)
   280  					_, err := applet.Create(ctx, req)
   281  					mock_sqlx.ExpectError(t, err, status.AppletNameConflict)
   282  				})
   283  				t.Run("#DatabaseError", func(t *testing.T) {
   284  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrDatabase).Times(1)
   285  					_, err := applet.Create(ctx, req)
   286  					mock_sqlx.ExpectError(t, err, status.DatabaseError)
   287  				})
   288  			})
   289  
   290  			patch = patch_modules.StrategyBatchCreate(patch, nil)
   291  
   292  			t.Run("#DeployUpsertByCodeFailed", func(t *testing.T) {
   293  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   294  				patch = patch_modules.DeployUpsertByCode(patch, nil, cause(t.Name()))
   295  				_, err := applet.Create(ctx, req)
   296  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   297  			})
   298  		})
   299  
   300  		t.Run("#Success", func(t *testing.T) {
   301  			d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   302  			patch = patch_modules.DeployUpsertByCode(patch, &models.Instance{}, nil)
   303  
   304  			r := *req
   305  			r.WasmCache = &wasm.Cache{}
   306  			_, err := applet.Create(ctx, &r)
   307  			NewWithT(t).Expect(err).To(BeNil())
   308  		})
   309  	})
   310  
   311  	t.Run("Update", func(t *testing.T) {
   312  		if runtime.GOOS == `darwin` {
   313  			return
   314  		}
   315  
   316  		patch := gomonkey.NewPatches()
   317  		defer patch.Reset()
   318  
   319  		var (
   320  			req  = &applet.UpdateReq{}
   321  			code = []byte("any")
   322  
   323  			header, err = transformer.NewFileHeader("file", "any_file", bytes.NewBuffer(code))
   324  		)
   325  		NewWithT(t).Expect(err).To(BeNil())
   326  
   327  		t.Run("#Failed", func(t *testing.T) {
   328  			t.Run("#ResourceCreateFailed", func(t *testing.T) {
   329  				r := *req
   330  				r.File = header
   331  
   332  				patch = patch_modules.ResourceCreate(patch, nil, nil, cause(t.Name()))
   333  				_, err = applet.Update(ctx, &r)
   334  				NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   335  			})
   336  
   337  			patch = patch_modules.ResourceCreate(patch, &models.Resource{}, code, nil)
   338  
   339  			t.Run("#UpdateStrategyFailed", func(t *testing.T) {
   340  				r := *req
   341  				r.Strategies = []models.StrategyInfo{{}}
   342  				t.Run("#StrategyRemoveFailed", func(t *testing.T) {
   343  					patch = patch_modules.StrategyRemove(patch, cause(t.Name()))
   344  					_, err = applet.Update(ctx, &r)
   345  					NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   346  				})
   347  
   348  				patch = patch_modules.StrategyRemove(patch, nil)
   349  
   350  				t.Run("#StrategyBatchCreateFailed", func(t *testing.T) {
   351  					patch = patch_modules.StrategyBatchCreate(patch, cause(t.Name()))
   352  					_, err = applet.Update(ctx, &r)
   353  					NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   354  				})
   355  			})
   356  
   357  			patch = patch_modules.StrategyBatchCreate(patch, nil)
   358  
   359  			t.Run("#UpdateAppletDatabaseFailed", func(t *testing.T) {
   360  				r := *req
   361  				r.AppletName = "any"
   362  				r.File = header
   363  
   364  				t.Run("#AppletNameConflict", func(t *testing.T) {
   365  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrConflict).Times(1)
   366  					_, err = applet.Update(ctx, &r)
   367  					mock_sqlx.ExpectError(t, err, status.AppletNameConflict)
   368  				})
   369  				t.Run("#DatabaseError", func(t *testing.T) {
   370  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrDatabase).Times(1)
   371  					_, err = applet.Update(ctx, &r)
   372  					mock_sqlx.ExpectError(t, err, status.DatabaseError)
   373  				})
   374  			})
   375  
   376  			d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(sqlmock.NewResult(1, 1), nil).AnyTimes()
   377  
   378  			t.Run("#UpdateAndDeployInstanceFailed", func(t *testing.T) {
   379  				r := *req
   380  				r.File = header
   381  				r.WasmCache = &wasm.Cache{}
   382  				t.Run("#DeployGetByAppletSFIDFailed", func(t *testing.T) {
   383  					patch = patch_modules.DeployGetByAppletSFID(patch, &models.Instance{}, cause(t.Name()))
   384  					_, err = applet.Update(ctx, &r)
   385  					NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   386  				})
   387  
   388  				patch = patch_modules.DeployGetByAppletSFID(patch, &models.Instance{}, nil)
   389  
   390  				t.Run("#DeployGetByAppletSFIDFailed", func(t *testing.T) {
   391  					patch = patch_modules.DeployUpsertByCode(patch, nil, cause(t.Name()))
   392  					_, err = applet.Update(ctx, &r)
   393  					NewWithT(t).Expect(err.Error()).To(Equal(t.Name()))
   394  				})
   395  			})
   396  		})
   397  		t.Run("#Success", func(t *testing.T) {
   398  			patch = patch_modules.DeployUpsertByCode(patch, &models.Instance{}, nil)
   399  
   400  			r := *req
   401  			_, err = applet.Update(ctx, &r)
   402  			NewWithT(t).Expect(err).To(BeNil())
   403  
   404  			r.Strategies = []models.StrategyInfo{{}}
   405  			_, err = applet.Update(ctx, &r)
   406  			NewWithT(t).Expect(err).To(BeNil())
   407  		})
   408  	})
   409  }