github.com/mailru/activerecord@v1.12.2/internal/app/argen_w_test.go (about)

     1  package app
     2  
     3  import (
     4  	"context"
     5  	"io/fs"
     6  	"os"
     7  	"path/filepath"
     8  	"reflect"
     9  	"sync"
    10  	"testing"
    11  
    12  	"github.com/mailru/activerecord/internal/pkg/ds"
    13  	"github.com/mailru/activerecord/internal/pkg/testutil"
    14  	"github.com/mailru/activerecord/pkg/octopus"
    15  	"gotest.tools/assert"
    16  	"gotest.tools/assert/cmp"
    17  )
    18  
    19  type args struct {
    20  	appInfo    ds.AppInfo
    21  	srcDir     string
    22  	dstDir     string
    23  	dstFixture string
    24  	modName    string
    25  }
    26  
    27  func TestArGen_addRecordPackage(t *testing.T) {
    28  	tempDirs := testutil.InitTmps()
    29  	defer tempDirs.Defer()
    30  
    31  	src, dst, err := tempDirs.CreateDirs(testutil.EmptyDstDir)
    32  	if err != nil {
    33  		t.Errorf("ArGen.Init() error = %v", err)
    34  		return
    35  	}
    36  
    37  	argen, err := Init(context.Background(), &testutil.TestAppInfo, src, dst, "", "github.com/mailru/activerecord")
    38  	if err != nil {
    39  		t.Errorf("ArGen.Init() error = %v", err)
    40  		return
    41  	}
    42  
    43  	emptyRP := ds.NewRecordPackage()
    44  
    45  	type args struct {
    46  		pkgName string
    47  	}
    48  	tests := []struct {
    49  		name    string
    50  		args    args
    51  		want    *ds.RecordPackage
    52  		wantErr bool
    53  	}{
    54  		{
    55  			name: "Pkg with camecase name",
    56  			args: args{
    57  				pkgName: "firstTestClassName",
    58  			},
    59  			wantErr: true,
    60  		},
    61  		{
    62  			name: "too long pkg name",
    63  			args: args{
    64  				pkgName: "secondtestclassnametooverylong",
    65  			},
    66  			wantErr: true,
    67  		},
    68  		{
    69  			name: "normal package name",
    70  			args: args{
    71  				pkgName: "foo",
    72  			},
    73  			wantErr: false,
    74  		},
    75  		{
    76  			name: "dup",
    77  			args: args{
    78  				pkgName: "foo",
    79  			},
    80  			wantErr: true,
    81  		},
    82  		{
    83  			name: "notdup",
    84  			args: args{
    85  				pkgName: "bar",
    86  			},
    87  			wantErr: false,
    88  			want:    emptyRP,
    89  		},
    90  	}
    91  
    92  	var got *ds.RecordPackage
    93  
    94  	for _, tt := range tests {
    95  		t.Run(tt.name, func(t *testing.T) {
    96  			got, err = argen.addRecordPackage(tt.args.pkgName)
    97  			if (err != nil) != tt.wantErr {
    98  				t.Errorf("AddRecordClass() error = %v, got = %+v, wantErr %v", err, argen, tt.wantErr)
    99  				return
   100  			}
   101  
   102  			if tt.want != nil && !reflect.DeepEqual(got, tt.want) {
   103  				t.Errorf("AddRecordClass() = %+v, want %+v", got, tt.want)
   104  			}
   105  		})
   106  	}
   107  
   108  	got, err = argen.addRecordPackage("yarp")
   109  	if err != nil {
   110  		t.Errorf("AddRecordClass() error = %s", err)
   111  		return
   112  	}
   113  
   114  	got.Backends = []string{"testbackend"}
   115  	emptyRP.Backends = append(emptyRP.Backends, "testbackend")
   116  
   117  	if !reflect.DeepEqual(argen.packagesParsed["yarp"], emptyRP) {
   118  		t.Errorf("ModifyRecordClass() = %+v, want %+v", argen.packagesParsed["yarp"], emptyRP)
   119  	}
   120  }
   121  
   122  func TestInternalInit(t *testing.T) {
   123  	tempDirs := testutil.InitTmps()
   124  	defer tempDirs.Defer()
   125  
   126  	srcEmpty, dstEmpty, err := tempDirs.CreateDirs(testutil.NonExistsDstDir)
   127  	if err != nil {
   128  		t.Errorf("error initialize dirs: %s", err)
   129  		return
   130  	}
   131  
   132  	tests := []struct {
   133  		name    string
   134  		args    args
   135  		want    *ArGen
   136  		wantErr bool
   137  	}{
   138  		{
   139  			name: "empty src dir",
   140  			args: args{
   141  				appInfo: testutil.TestAppInfo,
   142  				srcDir:  srcEmpty,
   143  				dstDir:  dstEmpty,
   144  				modName: "test.package.ar/activerecord/pkg.git",
   145  			},
   146  			want: &ArGen{
   147  				src:            srcEmpty,
   148  				dst:            dstEmpty,
   149  				srcEntry:       []fs.DirEntry{},
   150  				dstEntry:       []fs.DirEntry{},
   151  				packagesParsed: map[string]*ds.RecordPackage{},
   152  				packagesLock:   sync.Mutex{},
   153  				appInfo:        &testutil.TestAppInfo,
   154  				packagesLinked: map[string]string{},
   155  				modName:        "test.package.ar/activerecord/pkg.git",
   156  				fileToRemove:   map[string]bool{},
   157  			},
   158  			wantErr: false,
   159  		},
   160  	}
   161  	for _, tt := range tests {
   162  		t.Run(tt.name, func(t *testing.T) {
   163  			ctx := context.Background()
   164  			if tt.want != nil {
   165  				tt.want.ctx = ctx
   166  			}
   167  
   168  			got, err := Init(ctx, &tt.args.appInfo, tt.args.srcDir, tt.args.dstDir, tt.args.dstFixture, tt.args.modName)
   169  			if (err != nil) != tt.wantErr {
   170  				t.Errorf("Init() error = %v, res = %+v, wantErr %v", err, got, tt.wantErr)
   171  				return
   172  			}
   173  
   174  			if !reflect.DeepEqual(got, tt.want) {
   175  				t.Errorf("Init() = %+v, want %+v", got, tt.want)
   176  			}
   177  		})
   178  	}
   179  }
   180  
   181  func TestArGen_prepareDir(t *testing.T) {
   182  	tempDirs := testutil.InitTmps()
   183  	defer tempDirs.Defer()
   184  
   185  	srcNotEmpty, dstNotExist, err := tempDirs.CreateDirs(testutil.NonExistsDstDir)
   186  	if err != nil {
   187  		t.Errorf("can't initialize dirs: %s", err)
   188  	}
   189  
   190  	if _, err = os.CreateTemp(srcNotEmpty, "foo.go"); err != nil {
   191  		t.Errorf("error create tmp dir `%s` with repository declaration: %s", srcNotEmpty, err)
   192  		return
   193  	}
   194  
   195  	srcEntry, err := os.ReadDir(srcNotEmpty)
   196  	if err != nil {
   197  		t.Errorf("error open tmp dir `%s` with repository declaration: %s", srcNotEmpty, err)
   198  		return
   199  	}
   200  
   201  	type want struct {
   202  		srcEntry   []fs.DirEntry
   203  		dstEntry   []fs.DirEntry
   204  		dst        string
   205  		dstCreated bool
   206  	}
   207  
   208  	tests := []struct {
   209  		name    string
   210  		args    args
   211  		want    want
   212  		wantErr bool
   213  	}{
   214  		{
   215  			name: "prepare test",
   216  			args: args{
   217  				appInfo: testutil.TestAppInfo,
   218  				srcDir:  srcNotEmpty,
   219  				dstDir:  dstNotExist,
   220  				modName: "github.com/mailru/activerecord",
   221  			},
   222  			want: want{
   223  				srcEntry:   srcEntry,
   224  				dstEntry:   []fs.DirEntry{},
   225  				dst:        dstNotExist,
   226  				dstCreated: true,
   227  			},
   228  			wantErr: false,
   229  		},
   230  		{
   231  			name: "prepare fail test",
   232  			args: args{
   233  				appInfo: testutil.TestAppInfo,
   234  				srcDir:  "/non/exists/src/path",
   235  				dstDir:  "/non/exists/dst/path",
   236  				modName: "github.com/mailru/activerecord",
   237  			},
   238  			want:    want{},
   239  			wantErr: true,
   240  		},
   241  		{
   242  			name: "error dst dir",
   243  			args: args{
   244  				appInfo: testutil.TestAppInfo,
   245  				srcDir:  "/usr",
   246  				dstDir:  "/var",
   247  				modName: "github.com/mailru/activerecord",
   248  			},
   249  			want:    want{},
   250  			wantErr: true,
   251  		},
   252  	}
   253  	for _, tt := range tests {
   254  		t.Run(tt.name, func(t *testing.T) {
   255  			ctx := context.Background()
   256  			got, err := Init(ctx, &tt.args.appInfo, tt.args.srcDir, tt.args.dstDir, tt.args.dstFixture, tt.args.modName)
   257  			if (err != nil) != tt.wantErr {
   258  				t.Errorf("Init() error = %v, res = %+v, wantErr %v", err, got, tt.wantErr)
   259  				return
   260  			}
   261  
   262  			if err == nil {
   263  				if !reflect.DeepEqual(got.srcEntry, tt.want.srcEntry) {
   264  					t.Errorf("srcEntry got = %+v, want %+v", got.srcEntry, tt.want.srcEntry)
   265  					return
   266  				}
   267  
   268  				if !reflect.DeepEqual(got.dstEntry, tt.want.dstEntry) {
   269  					t.Errorf("srcEntry got = %+v, want %+v", got.dstEntry, tt.want.dstEntry)
   270  					return
   271  				}
   272  			}
   273  
   274  			if _, err := os.ReadDir(tt.want.dst); (err != nil && os.IsNotExist(err)) == tt.want.dstCreated {
   275  				t.Errorf("readDstErr got = %+v, want create %+v", err, tt.want.dstCreated)
   276  				return
   277  			}
   278  		})
   279  	}
   280  }
   281  
   282  func TestArGen_getExists(t *testing.T) {
   283  	tempDirs := testutil.InitTmps()
   284  	defer tempDirs.Defer()
   285  
   286  	srcEmpty, dstNotEmpty, err := tempDirs.CreateDirs(testutil.EmptyDstDir)
   287  	if err != nil {
   288  		t.Errorf("can't initialize dirs: %s", err)
   289  		return
   290  	}
   291  
   292  	entDir := filepath.Join(dstNotEmpty, "foo")
   293  	if err := os.Mkdir(entDir, 0755); err != nil {
   294  		t.Errorf("create dir into dst error: %s", err)
   295  		return
   296  	}
   297  
   298  	entFile := filepath.Join(entDir, "octopus.go")
   299  	if _, err := os.Create(entFile); err != nil {
   300  		t.Errorf("create file into dst error: %s", err)
   301  		return
   302  	}
   303  
   304  	type want struct {
   305  		dstEntry   []fs.DirEntry
   306  		existsFile []string
   307  	}
   308  
   309  	tests := []struct {
   310  		name    string
   311  		args    args
   312  		want    want
   313  		wantErr bool
   314  	}{
   315  		{
   316  			name: "prepare fail test",
   317  			args: args{
   318  				appInfo: testutil.TestAppInfo,
   319  				srcDir:  srcEmpty,
   320  				dstDir:  dstNotEmpty,
   321  				modName: "github.com/mailru/activerecord",
   322  			},
   323  			want: want{
   324  				dstEntry:   []fs.DirEntry{},
   325  				existsFile: []string{dstNotEmpty + "/foo", dstNotEmpty + "/foo/octopus.go"},
   326  			},
   327  			wantErr: false,
   328  		},
   329  	}
   330  	for _, tt := range tests {
   331  		t.Run(tt.name, func(t *testing.T) {
   332  			ctx := context.Background()
   333  			got, err := Init(ctx, &tt.args.appInfo, tt.args.srcDir, tt.args.dstDir, tt.args.dstFixture, tt.args.modName)
   334  			if (err != nil) != tt.wantErr {
   335  				t.Errorf("Init() error = %v, res = %+v, wantErr %v", err, got, tt.wantErr)
   336  				return
   337  			}
   338  
   339  			exists, err := got.getExists()
   340  
   341  			if err == nil {
   342  				if !reflect.DeepEqual(exists, tt.want.existsFile) {
   343  					t.Errorf("existsFile got = %+v, want %+v", exists, tt.want.existsFile)
   344  					return
   345  				}
   346  			}
   347  		})
   348  	}
   349  }
   350  
   351  func TestArGen_preparePackage(t *testing.T) {
   352  	type want struct {
   353  		modName       map[string]string
   354  		linkedObjects map[string]string
   355  	}
   356  
   357  	rpFoo := ds.NewRecordPackage()
   358  	rpFoo.Backends = []string{"octopus"}
   359  	rpFoo.Server = ds.ServerDeclaration{Host: "127.0.0.1", Port: "11011"}
   360  	rpFoo.Namespace = ds.NamespaceDeclaration{ObjectName: "0", PackageName: "foo", PublicName: "Foo"}
   361  
   362  	err := rpFoo.AddField(ds.FieldDeclaration{
   363  		Name:       "ID",
   364  		Format:     octopus.Int,
   365  		PrimaryKey: true,
   366  		Mutators:   []string{},
   367  		Size:       0,
   368  		Serializer: []string{},
   369  		ObjectLink: "",
   370  	})
   371  	if err != nil {
   372  		t.Errorf("can't prepare test data %s", err)
   373  		return
   374  	}
   375  
   376  	err = rpFoo.AddField(ds.FieldDeclaration{
   377  		Name:       "BarID",
   378  		Format:     octopus.Int,
   379  		PrimaryKey: false,
   380  		Mutators:   []string{},
   381  		Size:       0,
   382  		Serializer: []string{},
   383  		ObjectLink: "Bar",
   384  	})
   385  	if err != nil {
   386  		t.Errorf("can't prepare test data %s", err)
   387  		return
   388  	}
   389  
   390  	err = rpFoo.AddFieldObject(ds.FieldObject{
   391  		Name:       "Foo",
   392  		Key:        "ID",
   393  		ObjectName: "bar",
   394  		Field:      "BarID",
   395  		Unique:     true,
   396  	})
   397  	if err != nil {
   398  		t.Errorf("can't prepare test data %s", err)
   399  		return
   400  	}
   401  
   402  	rpBar := ds.NewRecordPackage()
   403  	rpBar.Backends = []string{"octopus"}
   404  	rpBar.Namespace = ds.NamespaceDeclaration{ObjectName: "1", PackageName: "bar", PublicName: "Bar"}
   405  
   406  	err = rpBar.AddField(ds.FieldDeclaration{
   407  		Name:       "ID",
   408  		Format:     octopus.Int,
   409  		PrimaryKey: false,
   410  		Mutators:   []string{},
   411  		Size:       0,
   412  		Serializer: []string{},
   413  		ObjectLink: "",
   414  	})
   415  	if err != nil {
   416  		t.Errorf("can't prepare test data %s", err)
   417  		return
   418  	}
   419  
   420  	tests := []struct {
   421  		name    string
   422  		fields  *ArGen
   423  		want    want
   424  		wantErr bool
   425  	}{
   426  		{
   427  			name: "empty package",
   428  			fields: &ArGen{
   429  				ctx:            context.Background(),
   430  				src:            "decl",
   431  				dst:            "gener",
   432  				srcEntry:       []fs.DirEntry{},
   433  				dstEntry:       []fs.DirEntry{},
   434  				packagesParsed: map[string]*ds.RecordPackage{},
   435  				packagesLock:   sync.Mutex{},
   436  				packagesLinked: map[string]string{},
   437  				appInfo:        &ds.AppInfo{},
   438  				modName:        "test.package.ar/activerecord/pkg.git",
   439  			},
   440  			want: want{
   441  				linkedObjects: map[string]string{},
   442  				modName:       map[string]string{},
   443  			},
   444  			wantErr: false,
   445  		},
   446  		{
   447  			name: "linked package",
   448  			fields: &ArGen{
   449  				ctx:            context.Background(),
   450  				src:            "decl",
   451  				dst:            "gener",
   452  				srcEntry:       []fs.DirEntry{},
   453  				dstEntry:       []fs.DirEntry{},
   454  				packagesParsed: map[string]*ds.RecordPackage{"foo": rpFoo, "bar": rpBar},
   455  				packagesLock:   sync.Mutex{},
   456  				packagesLinked: map[string]string{},
   457  				appInfo:        &ds.AppInfo{},
   458  				modName:        "test.package.ar/activerecord/pkg.git",
   459  			},
   460  			want: want{
   461  				linkedObjects: map[string]string{"bar": "bar", "foo": "foo"},
   462  				modName:       map[string]string{"foo": "test.package.ar/activerecord/pkg.git/gener/foo", "bar": "test.package.ar/activerecord/pkg.git/gener/bar"},
   463  			},
   464  			wantErr: false,
   465  		},
   466  	}
   467  	for _, tt := range tests {
   468  		t.Run(tt.name, func(t *testing.T) {
   469  			a := tt.fields
   470  			if err := a.prepareCheck(); (err != nil) != tt.wantErr {
   471  				t.Errorf("prepareCheck() error = %v, wantErr %v", err, tt.wantErr)
   472  			}
   473  
   474  			for pkg, rp := range a.packagesParsed {
   475  				wnt, ok := tt.want.modName[pkg]
   476  				if !ok {
   477  					t.Errorf("invalid declare test, want.modName for package %s not exists", pkg)
   478  					return
   479  				}
   480  
   481  				if rp.Namespace.ModuleName != wnt {
   482  					t.Errorf("preparePackage modName for file %s = %s, want %s", pkg, rp.Namespace.ModuleName, wnt)
   483  				}
   484  			}
   485  
   486  			if !reflect.DeepEqual(a.packagesLinked, tt.want.linkedObjects) {
   487  				t.Errorf("preparePackage linkedObjects = %+v, want %+v", a.packagesLinked, tt.want.linkedObjects)
   488  				return
   489  			}
   490  		})
   491  	}
   492  }
   493  
   494  func TestArGen_prepareCheck(t *testing.T) {
   495  	type fields struct {
   496  		packagesParsed map[string]*ds.RecordPackage
   497  		modName        string
   498  	}
   499  	tests := []struct {
   500  		name       string
   501  		fields     fields
   502  		want       map[string]*ds.RecordPackage
   503  		wantLinked map[string]string
   504  		wantErr    bool
   505  	}{
   506  		{
   507  			name: "simple package",
   508  			fields: fields{
   509  				modName: "testmodname",
   510  				packagesParsed: map[string]*ds.RecordPackage{
   511  					"test": {
   512  						Namespace: ds.NamespaceDeclaration{
   513  							PackageName: "testPackage",
   514  						},
   515  					},
   516  				},
   517  			},
   518  			wantErr: false,
   519  			want: map[string]*ds.RecordPackage{
   520  				"test": {
   521  					Namespace: ds.NamespaceDeclaration{
   522  						PackageName: "testPackage",
   523  						ModuleName:  "testmodname/testPackage",
   524  					},
   525  				},
   526  			},
   527  			wantLinked: map[string]string{
   528  				"testPackage": "test",
   529  			},
   530  		},
   531  	}
   532  	a := &ArGen{
   533  		ctx:            context.Background(),
   534  		src:            "",
   535  		dst:            "",
   536  		srcEntry:       []fs.DirEntry{},
   537  		dstEntry:       []fs.DirEntry{},
   538  		packagesLock:   sync.Mutex{},
   539  		packagesLinked: map[string]string{},
   540  		appInfo:        &ds.AppInfo{},
   541  	}
   542  	for _, tt := range tests {
   543  		t.Run(tt.name, func(t *testing.T) {
   544  			a.packagesParsed = tt.fields.packagesParsed
   545  			a.modName = tt.fields.modName
   546  			if err := a.prepareCheck(); (err != nil) != tt.wantErr {
   547  				t.Errorf("prepareCheck() error = %v, wantErr %v", err, tt.wantErr)
   548  			}
   549  
   550  			if !reflect.DeepEqual(a.packagesParsed, tt.want) {
   551  				if len(a.packagesParsed) != len(tt.want) {
   552  					t.Errorf("prepareCheck parsed got len = %d, want %d", len(a.packagesParsed), len(tt.want))
   553  				}
   554  
   555  				for key := range a.packagesParsed {
   556  					if !reflect.DeepEqual(a.packagesParsed[key], tt.want[key]) {
   557  						t.Errorf("prepareCheck parsed package %s = %+v, want %+v", key, a.packagesParsed[key], tt.want[key])
   558  					}
   559  				}
   560  			}
   561  
   562  			if !reflect.DeepEqual(a.packagesLinked, tt.wantLinked) {
   563  				t.Errorf("prepareCheck packageslinked got %+v, want %+v", a.packagesLinked, tt.wantLinked)
   564  			}
   565  		})
   566  	}
   567  }
   568  
   569  func Test_writeToFile(t *testing.T) {
   570  	tempDirs := testutil.InitTmps()
   571  	defer tempDirs.Defer()
   572  
   573  	dst, err := tempDirs.AddTempDir()
   574  	if err != nil {
   575  		t.Errorf("can't initialize dirs: %s", err)
   576  	}
   577  
   578  	type args struct {
   579  		dirPkg      string
   580  		dstFileName string
   581  		data        []byte
   582  	}
   583  	tests := []struct {
   584  		name    string
   585  		args    args
   586  		wantErr bool
   587  	}{
   588  		{
   589  			name: "success write",
   590  			args: args{
   591  				dirPkg:      dst,
   592  				dstFileName: filepath.Join(dst, "test.bla"),
   593  				data:        []byte("testbyte"),
   594  			},
   595  			wantErr: false,
   596  		},
   597  		{
   598  			name: "invalid file name",
   599  			args: args{
   600  				dirPkg:      dst,
   601  				dstFileName: "test.bla",
   602  				data:        []byte("testbyte"),
   603  			},
   604  			wantErr: true,
   605  		},
   606  	}
   607  	for _, tt := range tests {
   608  		t.Run(tt.name, func(t *testing.T) {
   609  			if err := writeToFile(tt.args.dirPkg, tt.args.dstFileName, tt.args.data); (err != nil) != tt.wantErr {
   610  				t.Errorf("writeToFile() error = %v, wantErr %v", err, tt.wantErr)
   611  			}
   612  		})
   613  	}
   614  }
   615  
   616  func TestArGen_parse(t *testing.T) {
   617  	tempDirs := testutil.InitTmps()
   618  	defer tempDirs.Defer()
   619  
   620  	repositoryName := "foo"
   621  	textTestPkg := `package repository
   622  
   623  //ar:serverHost:127.0.0.1;serverPort:11111;serverTimeout:500
   624  //ar:namespace:2
   625  //ar:backend:octopus
   626  type FieldsFoo struct {
   627  	Field1    int  ` + "`" + `ar:"size:5"` + "`" + `
   628  	Field2    string  ` + "`" + `ar:"size:5"` + "`" + `
   629  }
   630  
   631  type (
   632  	IndexesFoo struct {
   633  		Field1Field2 bool ` + "`" + `ar:"fields:Field1,Field2;primary_key"` + "`" + `
   634  	}
   635  	IndexPartsFoo struct {
   636  		Field1Part bool ` + "`" + `ar:"index:Field1Field2;fieldnum:1;selector:SelectByField1"` + "`" + `
   637  	}
   638  )
   639  
   640  type TriggersFoo struct {
   641  	RepairTuple bool ` + "`" + `ar:"pkg:github.com/mailru/activerecord-cookbook.git/example/model/repository/repair;func:Promoperiod;param:Defaults"` + "`" + `
   642  }
   643  `
   644  
   645  	srcRoot, err := tempDirs.AddTempDir()
   646  	if err != nil {
   647  		t.Errorf("can't initialize dir: %s", err)
   648  		return
   649  	}
   650  
   651  	src := filepath.Join(srcRoot, "model/repository/decl")
   652  	if err = os.MkdirAll(src, 0755); err != nil {
   653  		t.Errorf("prepare test files error: %s", err)
   654  		return
   655  	}
   656  
   657  	if err = os.WriteFile(filepath.Join(src, repositoryName+".go"), []byte(textTestPkg), 0644); err != nil {
   658  		t.Errorf("prepare test files error: %s", err)
   659  		return
   660  	}
   661  
   662  	tests := []struct {
   663  		name    string
   664  		fields  args
   665  		wantErr bool
   666  		want    map[string]*ds.RecordPackage
   667  	}{
   668  		{
   669  			name:    "simple package",
   670  			fields:  args{srcDir: src, dstDir: filepath.Join(srcRoot, "model/repository/cmpl")},
   671  			wantErr: false,
   672  			want: map[string]*ds.RecordPackage{
   673  				"foo": {
   674  					Namespace: ds.NamespaceDeclaration{ObjectName: "2", PublicName: "Foo", PackageName: "foo", ModuleName: "testmod"},
   675  					Server:    ds.ServerDeclaration{Timeout: 500, Host: "127.0.0.1", Port: "11111"},
   676  					Fields: []ds.FieldDeclaration{
   677  						{Name: "Field1", Format: "int", PrimaryKey: true, Mutators: []string{}, Size: 5, Serializer: []string{}},
   678  						{Name: "Field2", Format: "string", PrimaryKey: true, Mutators: []string{}, Size: 5, Serializer: []string{}},
   679  					},
   680  					FieldsMap:       map[string]int{"Field1": 0, "Field2": 1},
   681  					FieldsObjectMap: map[string]ds.FieldObject{},
   682  					ProcOutFields:   map[int]ds.ProcFieldDeclaration{},
   683  					ProcFieldsMap:   map[string]int{},
   684  					Indexes: []ds.IndexDeclaration{
   685  						{
   686  							Name:     "Field1Field2",
   687  							Num:      0,
   688  							Selector: "SelectByField1Field2",
   689  							Fields:   []int{0, 1},
   690  							FieldsMap: map[string]ds.IndexField{
   691  								"Field1": {IndField: 0, Order: 0},
   692  								"Field2": {IndField: 1, Order: 0},
   693  							},
   694  							Primary: true,
   695  							Unique:  true,
   696  						},
   697  						{Name: "Field1Part",
   698  							Num:      0,
   699  							Selector: "SelectByField1",
   700  							Fields:   []int{0},
   701  							FieldsMap: map[string]ds.IndexField{
   702  								"Field1": {IndField: 0, Order: 0},
   703  							},
   704  							Primary: false,
   705  							Unique:  false,
   706  							Partial: true,
   707  						},
   708  					},
   709  					IndexMap:      map[string]int{"Field1Field2": 0, "Field1Part": 1},
   710  					SelectorMap:   map[string]int{"SelectByField1": 1, "SelectByField1Field2": 0},
   711  					Backends:      []string{"octopus"},
   712  					SerializerMap: map[string]ds.SerializerDeclaration{},
   713  					ImportPackage: ds.ImportPackage{Imports: []ds.ImportDeclaration{
   714  						{
   715  							Path:       "github.com/mailru/activerecord-cookbook.git/example/model/repository/repair",
   716  							ImportName: "triggerRepairTuple",
   717  						},
   718  					},
   719  						ImportMap:    map[string]int{"github.com/mailru/activerecord-cookbook.git/example/model/repository/repair": 0},
   720  						ImportPkgMap: map[string]int{"triggerRepairTuple": 0}},
   721  					TriggerMap: map[string]ds.TriggerDeclaration{
   722  						"RepairTuple": {
   723  							Name:       "RepairTuple",
   724  							Pkg:        "github.com/mailru/activerecord-cookbook.git/example/model/repository/repair",
   725  							Func:       "Promoperiod",
   726  							ImportName: "triggerRepairTuple",
   727  							Params:     map[string]bool{"Defaults": true},
   728  						},
   729  					},
   730  					FlagMap:               map[string]ds.FlagDeclaration{},
   731  					MutatorMap:            map[string]ds.MutatorDeclaration{},
   732  					ImportStructFieldsMap: map[string][]ds.PartialFieldDeclaration{},
   733  					LinkedStructsMap:      map[string]ds.LinkedPackageDeclaration{},
   734  				},
   735  			},
   736  		},
   737  	}
   738  
   739  	for _, tt := range tests {
   740  		t.Run(tt.name, func(t *testing.T) {
   741  			a, err := Init(context.Background(), &ds.AppInfo{}, tt.fields.srcDir, tt.fields.dstDir, tt.fields.dstFixture, "testmod")
   742  			if err != nil {
   743  				t.Errorf("can't init argen: %s", err)
   744  				return
   745  			}
   746  
   747  			if err := a.parse(); (err != nil) != tt.wantErr {
   748  				t.Errorf("ArGen.parse() error = %v, wantErr %v", err, tt.wantErr)
   749  			}
   750  
   751  			if len(a.packagesParsed) != len(tt.want) {
   752  				t.Errorf("Mismatch len keys = %+v, want %+v", a.packagesParsed, tt.want)
   753  				return
   754  			}
   755  
   756  			for key, pkg := range a.packagesParsed {
   757  				assert.Check(t, cmp.DeepEqual(tt.want[key], pkg), "Invalid response, test `%s`", key)
   758  			}
   759  		})
   760  	}
   761  }