github.com/mailru/activerecord@v1.12.2/internal/pkg/parser/parser_w_test.go (about)

     1  package parser
     2  
     3  import (
     4  	"go/ast"
     5  	"go/token"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/mailru/activerecord/internal/pkg/ds"
    10  	"github.com/mailru/activerecord/pkg/octopus"
    11  )
    12  
    13  func Test_parseDoc(t *testing.T) {
    14  	type args struct {
    15  		dst  *ds.RecordPackage
    16  		docs *ast.CommentGroup
    17  	}
    18  
    19  	tests := []struct {
    20  		name    string
    21  		args    args
    22  		want    *ds.RecordPackage
    23  		wantErr bool
    24  	}{
    25  		{
    26  			name: "doc",
    27  			args: args{
    28  				dst: ds.NewRecordPackage(),
    29  				docs: &ast.CommentGroup{
    30  					List: []*ast.Comment{
    31  						{Text: `//ar:serverHost:127.0.0.1;serverPort:11011;serverTimeout:500`},
    32  						{Text: `//ar:namespace:5`},
    33  						{Text: `//ar:backend:octopus`},
    34  					},
    35  				},
    36  			},
    37  			wantErr: false,
    38  			want: &ds.RecordPackage{
    39  				Server: ds.ServerDeclaration{
    40  					Host:    "127.0.0.1",
    41  					Port:    "11011",
    42  					Timeout: 500,
    43  				},
    44  				Namespace: ds.NamespaceDeclaration{
    45  					ObjectName:  "5",
    46  					PublicName:  "",
    47  					PackageName: "",
    48  				},
    49  				Backends:              []string{"octopus"},
    50  				Fields:                []ds.FieldDeclaration{},
    51  				FieldsMap:             map[string]int{},
    52  				ProcFieldsMap:         map[string]int{},
    53  				ProcOutFields:         map[int]ds.ProcFieldDeclaration{},
    54  				FieldsObjectMap:       map[string]ds.FieldObject{},
    55  				Indexes:               []ds.IndexDeclaration{},
    56  				IndexMap:              map[string]int{},
    57  				SelectorMap:           map[string]int{},
    58  				ImportPackage:         ds.NewImportPackage(),
    59  				SerializerMap:         map[string]ds.SerializerDeclaration{},
    60  				TriggerMap:            map[string]ds.TriggerDeclaration{},
    61  				FlagMap:               map[string]ds.FlagDeclaration{},
    62  				MutatorMap:            map[string]ds.MutatorDeclaration{},
    63  				ImportStructFieldsMap: map[string][]ds.PartialFieldDeclaration{},
    64  				LinkedStructsMap:      map[string]ds.LinkedPackageDeclaration{},
    65  			},
    66  		},
    67  		{
    68  			name: "docComment",
    69  			args: args{
    70  				dst: ds.NewRecordPackage(),
    71  				docs: &ast.CommentGroup{
    72  					List: []*ast.Comment{
    73  						{Text: `//blablabla`},
    74  					},
    75  				},
    76  			},
    77  			wantErr: false,
    78  			want:    ds.NewRecordPackage(),
    79  		},
    80  		{
    81  			name: "docError",
    82  			args: args{
    83  				dst: ds.NewRecordPackage(),
    84  				docs: &ast.CommentGroup{
    85  					List: []*ast.Comment{
    86  						{Text: `//ar:fdgsdsfgdf`},
    87  					},
    88  				},
    89  			},
    90  			wantErr: true,
    91  			want:    ds.NewRecordPackage(),
    92  		},
    93  	}
    94  	for _, tt := range tests {
    95  		t.Run(tt.name, func(t *testing.T) {
    96  			if err := parseDoc(tt.args.dst, string(Fields), tt.args.docs); (err != nil) != tt.wantErr {
    97  				t.Errorf("parseDoc() error = %v, wantErr %v", err, tt.wantErr)
    98  				return
    99  			}
   100  
   101  			if !reflect.DeepEqual(tt.args.dst, tt.want) {
   102  				t.Errorf("parseDoc() dst = %+v, want %+v", tt.args.dst, tt.want)
   103  				return
   104  			}
   105  		})
   106  	}
   107  }
   108  
   109  func Test_parseGen(t *testing.T) {
   110  	type args struct {
   111  		dst  *ds.RecordPackage
   112  		genD *ast.GenDecl
   113  	}
   114  	w := ds.NewRecordPackage()
   115  	w.Backends = []string{"octopus"}
   116  	w.Namespace = ds.NamespaceDeclaration{
   117  		ObjectName:  "5",
   118  		PublicName:  "Baz",
   119  		PackageName: "baz",
   120  	}
   121  	w.Server = ds.ServerDeclaration{
   122  		Timeout: 500,
   123  		Host:    "127.0.0.1",
   124  		Port:    "11011",
   125  	}
   126  	wLinked := ds.NewRecordPackage()
   127  	wLinked.Backends = []string{"octopus"}
   128  	wLinked.Namespace = ds.NamespaceDeclaration{
   129  		ObjectName:  "5",
   130  		PublicName:  "Foo",
   131  		PackageName: "foo",
   132  	}
   133  	wLinked.Server = ds.ServerDeclaration{
   134  		Timeout: 500,
   135  		Host:    "127.0.0.1",
   136  		Port:    "11011",
   137  	}
   138  	wLinked.FieldsMap["ID"] = len(wLinked.Fields)
   139  	wLinked.Fields = append(wLinked.Fields, ds.FieldDeclaration{
   140  		Name:       "ID",
   141  		Format:     octopus.Int,
   142  		PrimaryKey: true,
   143  		Mutators:   []string{},
   144  		Size:       0,
   145  		Serializer: []string{},
   146  		ObjectLink: "",
   147  	})
   148  	wLinked.FieldsMap["BarID"] = len(wLinked.Fields)
   149  	wLinked.Fields = append(wLinked.Fields, ds.FieldDeclaration{
   150  		Name:       "BarID",
   151  		Format:     octopus.Int,
   152  		PrimaryKey: false,
   153  		Mutators:   []string{},
   154  		Size:       0,
   155  		Serializer: []string{},
   156  		ObjectLink: "Bar",
   157  	})
   158  	wLinked.FieldsObjectMap["Bar"] = ds.FieldObject{
   159  		Name:       "Bar",
   160  		Key:        "ID",
   161  		ObjectName: "bar",
   162  		Field:      "BarID",
   163  		Unique:     true,
   164  	}
   165  	wantIndex := ds.IndexDeclaration{
   166  		Name:      "ID",
   167  		Primary:   true,
   168  		Fields:    []int{0},
   169  		FieldsMap: map[string]ds.IndexField{"ID": {IndField: 0, Order: 0}},
   170  		Selector:  "SelectByID",
   171  		Unique:    true,
   172  		Num:       0,
   173  	}
   174  	wLinked.IndexMap[wantIndex.Name] = len(wLinked.Indexes)
   175  	wLinked.SelectorMap[wantIndex.Selector] = len(wLinked.Indexes)
   176  	wLinked.Indexes = append(wLinked.Indexes, wantIndex)
   177  
   178  	tests := []struct {
   179  		name    string
   180  		args    args
   181  		wantErr bool
   182  		want    *ds.RecordPackage
   183  	}{
   184  		{
   185  			name: "private and public names",
   186  			args: args{
   187  				dst: ds.NewRecordPackage(),
   188  				genD: &ast.GenDecl{
   189  					Tok: token.TYPE,
   190  					Doc: &ast.CommentGroup{
   191  						List: []*ast.Comment{
   192  							{Text: `//ar:serverHost:127.0.0.1;serverPort:11011;serverTimeout:500`},
   193  							{Text: `//ar:namespace:5`},
   194  							{Text: `//ar:backend:octopus`},
   195  						},
   196  					},
   197  					Specs: []ast.Spec{
   198  						&ast.TypeSpec{
   199  							Type: &ast.StructType{
   200  								Fields: &ast.FieldList{
   201  									List: []*ast.Field{},
   202  								},
   203  							},
   204  							Name: &ast.Ident{
   205  								Name: "FieldsBaz",
   206  							},
   207  						},
   208  					},
   209  				},
   210  			},
   211  			wantErr: false,
   212  			want:    w,
   213  		},
   214  		{
   215  			name: "Invalid names in struct",
   216  			args: args{
   217  				dst: ds.NewRecordPackage(),
   218  				genD: &ast.GenDecl{
   219  					Tok: token.TYPE,
   220  					Doc: &ast.CommentGroup{
   221  						List: []*ast.Comment{
   222  							{Text: `//ar:serverHost:127.0.0.1;serverPort:11011;serverTimeout:500`},
   223  							{Text: `//ar:namespace:5`},
   224  							{Text: `//ar:backend:octopus`},
   225  						},
   226  					},
   227  					Specs: []ast.Spec{
   228  						&ast.TypeSpec{
   229  							Type: &ast.StructType{
   230  								Fields: &ast.FieldList{
   231  									List: []*ast.Field{},
   232  								},
   233  							},
   234  							Name: &ast.Ident{
   235  								Name: "FieldsBaz",
   236  							},
   237  						},
   238  						&ast.TypeSpec{
   239  							Type: &ast.StructType{
   240  								Fields: &ast.FieldList{
   241  									List: []*ast.Field{},
   242  								},
   243  							},
   244  							Name: &ast.Ident{
   245  								Name: "IndexesInvalid",
   246  							},
   247  						},
   248  					},
   249  				},
   250  			},
   251  			wantErr: true,
   252  			want:    w,
   253  		},
   254  		{
   255  			name: "linked objects",
   256  			args: args{
   257  				dst: ds.NewRecordPackage(),
   258  				genD: &ast.GenDecl{
   259  					Tok: token.TYPE,
   260  					Doc: &ast.CommentGroup{
   261  						List: []*ast.Comment{
   262  							{Text: `//ar:serverHost:127.0.0.1;serverPort:11011;serverTimeout:500`},
   263  							{Text: `//ar:namespace:5`},
   264  							{Text: `//ar:backend:octopus`},
   265  						},
   266  					},
   267  					Specs: []ast.Spec{
   268  						&ast.TypeSpec{
   269  							Type: &ast.StructType{
   270  								Fields: &ast.FieldList{
   271  									List: []*ast.Field{
   272  										{
   273  											Names: []*ast.Ident{{Name: "ID"}},
   274  											Type:  &ast.Ident{Name: "int"},
   275  											Tag:   &ast.BasicLit{Value: "`" + `ar:"primary_key"` + "`"},
   276  										},
   277  										{
   278  											Names: []*ast.Ident{{Name: "BarID"}},
   279  											Type:  &ast.Ident{Name: "int"},
   280  											Tag:   &ast.BasicLit{Value: "`" + `ar:""` + "`"},
   281  										},
   282  									},
   283  								},
   284  							},
   285  							Name: &ast.Ident{
   286  								Name: "FieldsFoo",
   287  							},
   288  						},
   289  						&ast.TypeSpec{
   290  							Type: &ast.StructType{
   291  								Fields: &ast.FieldList{
   292  									List: []*ast.Field{
   293  										{
   294  											Names: []*ast.Ident{{Name: "Bar"}},
   295  											Type:  &ast.Ident{Name: "bool"},
   296  											Tag:   &ast.BasicLit{Value: "`" + `ar:"key:ID;object:bar;field:BarID"` + "`"},
   297  										},
   298  									},
   299  								},
   300  							},
   301  							Name: &ast.Ident{
   302  								Name: "FieldsObjectFoo",
   303  							},
   304  						},
   305  					},
   306  				},
   307  			},
   308  			wantErr: false,
   309  			want:    wLinked,
   310  		},
   311  	}
   312  	for _, tt := range tests {
   313  		t.Run(tt.name, func(t *testing.T) {
   314  			if err := parseGen(tt.args.dst, tt.args.genD); (err != nil) != tt.wantErr {
   315  				t.Errorf("parseGen() error = %v, wantErr %v", err, tt.wantErr)
   316  				return
   317  			}
   318  
   319  			if !reflect.DeepEqual(tt.args.dst, tt.want) {
   320  				t.Errorf("parseGen() %+v, want %+v", tt.args.dst, tt.want)
   321  			}
   322  		})
   323  	}
   324  }
   325  
   326  func Test_parseAst(t *testing.T) {
   327  	type args struct {
   328  		pkgName string
   329  		decls   []ast.Decl
   330  		rc      *ds.RecordPackage
   331  	}
   332  	tests := []struct {
   333  		name    string
   334  		args    args
   335  		wantErr bool
   336  		want    *ds.RecordPackage
   337  	}{
   338  		{
   339  			name: "private and public names",
   340  			args: args{
   341  				rc: ds.NewRecordPackage(),
   342  				decls: []ast.Decl{
   343  					&ast.GenDecl{
   344  						Tok: token.TYPE,
   345  						Doc: &ast.CommentGroup{
   346  							List: []*ast.Comment{
   347  								{Text: `//ar:serverHost:127.0.0.1;serverPort:11011;serverTimeout:500`},
   348  								{Text: `//ar:namespace:5`},
   349  								{Text: `//ar:backend:octopus`},
   350  							},
   351  						},
   352  						Specs: []ast.Spec{
   353  							&ast.TypeSpec{
   354  								Type: &ast.StructType{
   355  									Fields: &ast.FieldList{
   356  										List: []*ast.Field{},
   357  									},
   358  								},
   359  								Name: &ast.Ident{
   360  									Name: "FieldsBaz",
   361  								},
   362  							},
   363  						},
   364  					},
   365  				},
   366  			},
   367  			wantErr: false,
   368  			want: &ds.RecordPackage{
   369  				Server:                ds.ServerDeclaration{Timeout: 500, Host: "127.0.0.1", Port: "11011"},
   370  				Namespace:             ds.NamespaceDeclaration{ObjectName: "5", PublicName: "Baz", PackageName: "baz"},
   371  				ProcFieldsMap:         map[string]int{},
   372  				ProcOutFields:         map[int]ds.ProcFieldDeclaration{},
   373  				Fields:                []ds.FieldDeclaration{},
   374  				FieldsMap:             map[string]int{},
   375  				FieldsObjectMap:       map[string]ds.FieldObject{},
   376  				Indexes:               []ds.IndexDeclaration{},
   377  				IndexMap:              map[string]int{},
   378  				SelectorMap:           map[string]int{},
   379  				Backends:              []string{"octopus"},
   380  				SerializerMap:         map[string]ds.SerializerDeclaration{},
   381  				ImportPackage:         ds.NewImportPackage(),
   382  				TriggerMap:            map[string]ds.TriggerDeclaration{},
   383  				FlagMap:               map[string]ds.FlagDeclaration{},
   384  				MutatorMap:            map[string]ds.MutatorDeclaration{},
   385  				ImportStructFieldsMap: map[string][]ds.PartialFieldDeclaration{},
   386  				LinkedStructsMap:      map[string]ds.LinkedPackageDeclaration{},
   387  			},
   388  		},
   389  	}
   390  	for _, tt := range tests {
   391  		t.Run(tt.name, func(t *testing.T) {
   392  			if err := parseAst(tt.args.pkgName, tt.args.decls, tt.args.rc); (err != nil) != tt.wantErr {
   393  				t.Errorf("parseAst() error = %v, wantErr %v", err, tt.wantErr)
   394  			}
   395  
   396  			if !reflect.DeepEqual(tt.args.rc, tt.want) {
   397  				t.Errorf("parseAst() %+v, want %+v", tt.args.rc, tt.want)
   398  			}
   399  		})
   400  	}
   401  }