github.com/aavshr/aws-sdk-go@v1.41.3/internal/ini/ini_parser_test.go (about)

     1  //go:build go1.7
     2  // +build go1.7
     3  
     4  package ini
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"io"
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  func TestParser(t *testing.T) {
    15  	xID, _, _ := newLitToken([]rune("x = 1234"))
    16  	s3ID, _, _ := newLitToken([]rune("s3 = 1234"))
    17  	fooSlashes, _, _ := newLitToken([]rune("//foo"))
    18  
    19  	regionID, _, _ := newLitToken([]rune("region"))
    20  	regionLit, _, _ := newLitToken([]rune(`"us-west-2"`))
    21  	regionNoQuotesLit, _, _ := newLitToken([]rune("us-west-2"))
    22  
    23  	credentialID, _, _ := newLitToken([]rune("credential_source"))
    24  	ec2MetadataLit, _, _ := newLitToken([]rune("Ec2InstanceMetadata"))
    25  
    26  	outputID, _, _ := newLitToken([]rune("output"))
    27  	outputLit, _, _ := newLitToken([]rune("json"))
    28  
    29  	sepInValueID, _, _ := newLitToken([]rune("sepInValue"))
    30  	sepInValueLit := newToken(TokenOp, []rune("=:[foo]]bar["), StringType)
    31  
    32  	equalOp, _, _ := newOpToken([]rune("= 1234"))
    33  	equalColonOp, _, _ := newOpToken([]rune(": 1234"))
    34  	numLit, _, _ := newLitToken([]rune("1234"))
    35  	defaultID, _, _ := newLitToken([]rune("default"))
    36  	assumeID, _, _ := newLitToken([]rune("assumerole"))
    37  
    38  	defaultProfileStmt := newSectionStatement(defaultID)
    39  	assumeProfileStmt := newSectionStatement(assumeID)
    40  
    41  	fooSlashesExpr := newExpression(fooSlashes)
    42  
    43  	xEQ1234 := newEqualExpr(newExpression(xID), equalOp)
    44  	xEQ1234.AppendChild(newExpression(numLit))
    45  	xEQColon1234 := newEqualExpr(newExpression(xID), equalColonOp)
    46  	xEQColon1234.AppendChild(newExpression(numLit))
    47  
    48  	regionEQRegion := newEqualExpr(newExpression(regionID), equalOp)
    49  	regionEQRegion.AppendChild(newExpression(regionLit))
    50  
    51  	noQuotesRegionEQRegion := newEqualExpr(newExpression(regionID), equalOp)
    52  	noQuotesRegionEQRegion.AppendChild(newExpression(regionNoQuotesLit))
    53  
    54  	credEQExpr := newEqualExpr(newExpression(credentialID), equalOp)
    55  	credEQExpr.AppendChild(newExpression(ec2MetadataLit))
    56  
    57  	outputEQExpr := newEqualExpr(newExpression(outputID), equalOp)
    58  	outputEQExpr.AppendChild(newExpression(outputLit))
    59  
    60  	sepInValueExpr := newEqualExpr(newExpression(sepInValueID), equalOp)
    61  	sepInValueExpr.AppendChild(newExpression(sepInValueLit))
    62  
    63  	cases := []struct {
    64  		name          string
    65  		r             io.Reader
    66  		expectedStack []AST
    67  		expectedError bool
    68  	}{
    69  		{
    70  			name: "semicolon comment",
    71  			r:    bytes.NewBuffer([]byte(`;foo`)),
    72  			expectedStack: []AST{
    73  				newCommentStatement(newToken(TokenComment, []rune(";foo"), NoneType)),
    74  			},
    75  		},
    76  		{
    77  			name: "0==0",
    78  			r:    bytes.NewBuffer([]byte(`0==0`)),
    79  			expectedStack: []AST{
    80  				func() AST {
    81  					equalExpr := newEqualExpr(newExpression(newToken(TokenLit, []rune("0"), StringType)), equalOp)
    82  					equalExpr.AppendChild(newExpression(newToken(TokenOp, []rune("=0"), StringType)))
    83  					return newExprStatement(equalExpr)
    84  				}(),
    85  			},
    86  		},
    87  		{
    88  			name: "0=:0",
    89  			r:    bytes.NewBuffer([]byte(`0=:0`)),
    90  			expectedStack: []AST{
    91  				func() AST {
    92  					equalExpr := newEqualExpr(newExpression(newToken(TokenLit, []rune("0"), StringType)), equalOp)
    93  					equalExpr.AppendChild(newExpression(newToken(TokenOp, []rune(":0"), StringType)))
    94  					return newExprStatement(equalExpr)
    95  				}(),
    96  			},
    97  		},
    98  		{
    99  			name: "0:=0",
   100  			r:    bytes.NewBuffer([]byte(`0:=0`)),
   101  			expectedStack: []AST{
   102  				func() AST {
   103  					equalExpr := newEqualExpr(newExpression(newToken(TokenLit, []rune("0"), StringType)), equalColonOp)
   104  					equalExpr.AppendChild(newExpression(newToken(TokenOp, []rune("=0"), StringType)))
   105  					return newExprStatement(equalExpr)
   106  				}(),
   107  			},
   108  		},
   109  		{
   110  			name: "0::0",
   111  			r:    bytes.NewBuffer([]byte(`0::0`)),
   112  			expectedStack: []AST{
   113  				func() AST {
   114  					equalExpr := newEqualExpr(newExpression(newToken(TokenLit, []rune("0"), StringType)), equalColonOp)
   115  					equalExpr.AppendChild(newExpression(newToken(TokenOp, []rune(":0"), StringType)))
   116  					return newExprStatement(equalExpr)
   117  				}(),
   118  			},
   119  		},
   120  		{
   121  			name: "section with variable",
   122  			r:    bytes.NewBuffer([]byte(`[ default ]x`)),
   123  			expectedStack: []AST{
   124  				newCompletedSectionStatement(
   125  					defaultProfileStmt,
   126  				),
   127  				newExpression(xID),
   128  			},
   129  		},
   130  		{
   131  			name: "# comment",
   132  			r:    bytes.NewBuffer([]byte(`# foo`)),
   133  			expectedStack: []AST{
   134  				newCommentStatement(newToken(TokenComment, []rune("# foo"), NoneType)),
   135  			},
   136  		},
   137  		{
   138  			name: "// not a comment",
   139  			r:    bytes.NewBuffer([]byte(`//foo`)),
   140  			expectedStack: []AST{
   141  				fooSlashesExpr,
   142  			},
   143  		},
   144  		{
   145  			name: "multiple comments",
   146  			r: bytes.NewBuffer([]byte(`;foo
   147  					# baz
   148  					`)),
   149  			expectedStack: []AST{
   150  				newCommentStatement(newToken(TokenComment, []rune(";foo"), NoneType)),
   151  				newCommentStatement(newToken(TokenComment, []rune("# baz"), NoneType)),
   152  			},
   153  		},
   154  		{
   155  			name: "comment followed by skip state",
   156  			r: bytes.NewBuffer([]byte(`;foo
   157  			//foo
   158  					# baz
   159  					`)),
   160  			expectedStack: []AST{
   161  				newCommentStatement(newToken(TokenComment, []rune(";foo"), NoneType)),
   162  			},
   163  		},
   164  		{
   165  			name: "assignment",
   166  			r:    bytes.NewBuffer([]byte(`x = 1234`)),
   167  			expectedStack: []AST{
   168  				newExprStatement(xEQ1234),
   169  			},
   170  		},
   171  		{
   172  			name: "assignment spaceless",
   173  			r:    bytes.NewBuffer([]byte(`x=1234`)),
   174  			expectedStack: []AST{
   175  				newExprStatement(xEQ1234),
   176  			},
   177  		},
   178  		{
   179  			name: "assignment :",
   180  			r:    bytes.NewBuffer([]byte(`x : 1234`)),
   181  			expectedStack: []AST{
   182  				newExprStatement(xEQColon1234),
   183  			},
   184  		},
   185  		{
   186  			name: "assignment : no spaces",
   187  			r:    bytes.NewBuffer([]byte(`x:1234`)),
   188  			expectedStack: []AST{
   189  				newExprStatement(xEQColon1234),
   190  			},
   191  		},
   192  		{
   193  			name: "section expression",
   194  			r:    bytes.NewBuffer([]byte(`[ default ]`)),
   195  			expectedStack: []AST{
   196  				newCompletedSectionStatement(
   197  					defaultProfileStmt,
   198  				),
   199  			},
   200  		},
   201  		{
   202  			name: "section expression no spaces",
   203  			r:    bytes.NewBuffer([]byte(`[default]`)),
   204  			expectedStack: []AST{
   205  				newCompletedSectionStatement(
   206  					defaultProfileStmt,
   207  				),
   208  			},
   209  		},
   210  		{
   211  			name: "section statement",
   212  			r: bytes.NewBuffer([]byte(`[default]
   213  							region="us-west-2"`)),
   214  			expectedStack: []AST{
   215  				newCompletedSectionStatement(
   216  					defaultProfileStmt,
   217  				),
   218  				newExprStatement(regionEQRegion),
   219  			},
   220  		},
   221  		{
   222  			name: "complex section statement",
   223  			r: bytes.NewBuffer([]byte(`[default]
   224  		region = us-west-2
   225  		credential_source = Ec2InstanceMetadata
   226  		output = json
   227  
   228  		[assumerole]
   229  		output = json
   230  		region = us-west-2
   231  				`)),
   232  			expectedStack: []AST{
   233  				newCompletedSectionStatement(
   234  					defaultProfileStmt,
   235  				),
   236  				newExprStatement(noQuotesRegionEQRegion),
   237  				newExprStatement(credEQExpr),
   238  				newExprStatement(outputEQExpr),
   239  				newCompletedSectionStatement(
   240  					assumeProfileStmt,
   241  				),
   242  				newExprStatement(outputEQExpr),
   243  				newExprStatement(noQuotesRegionEQRegion),
   244  			},
   245  		},
   246  		{
   247  			name: "complex section statement with nested params",
   248  			r: bytes.NewBuffer([]byte(`[default]
   249  s3 =
   250  	foo=bar
   251  	bar=baz
   252  region = us-west-2
   253  credential_source = Ec2InstanceMetadata
   254  output = json
   255  
   256  [assumerole]
   257  output = json
   258  region = us-west-2
   259  				`)),
   260  			expectedStack: []AST{
   261  				newCompletedSectionStatement(
   262  					defaultProfileStmt,
   263  				),
   264  				newSkipStatement(newEqualExpr(newExpression(s3ID), equalOp)),
   265  				newExprStatement(noQuotesRegionEQRegion),
   266  				newExprStatement(credEQExpr),
   267  				newExprStatement(outputEQExpr),
   268  				newCompletedSectionStatement(
   269  					assumeProfileStmt,
   270  				),
   271  				newExprStatement(outputEQExpr),
   272  				newExprStatement(noQuotesRegionEQRegion),
   273  			},
   274  		},
   275  		{
   276  			name: "complex section statement",
   277  			r: bytes.NewBuffer([]byte(`[default]
   278  region = us-west-2
   279  credential_source = Ec2InstanceMetadata
   280  s3 =
   281  	foo=bar
   282  	bar=baz
   283  output = json
   284  
   285  [assumerole]
   286  output = json
   287  region = us-west-2
   288  				`)),
   289  			expectedStack: []AST{
   290  				newCompletedSectionStatement(
   291  					defaultProfileStmt,
   292  				),
   293  				newExprStatement(noQuotesRegionEQRegion),
   294  				newExprStatement(credEQExpr),
   295  				newSkipStatement(newEqualExpr(newExpression(s3ID), equalOp)),
   296  				newExprStatement(outputEQExpr),
   297  				newCompletedSectionStatement(
   298  					assumeProfileStmt,
   299  				),
   300  				newExprStatement(outputEQExpr),
   301  				newExprStatement(noQuotesRegionEQRegion),
   302  			},
   303  		},
   304  		{
   305  			name: "missing section statement",
   306  			r: bytes.NewBuffer([]byte(
   307  				`[default]
   308  s3 =
   309  [assumerole]
   310  output = json
   311  				`)),
   312  			expectedStack: []AST{
   313  				newCompletedSectionStatement(
   314  					defaultProfileStmt,
   315  				),
   316  				newSkipStatement(newEqualExpr(newExpression(s3ID), equalOp)),
   317  				newCompletedSectionStatement(
   318  					assumeProfileStmt,
   319  				),
   320  				newExprStatement(outputEQExpr),
   321  			},
   322  		},
   323  		{
   324  			name: "missing right hand expression in the last statement in the file",
   325  			r: bytes.NewBuffer([]byte(
   326  				`[default]
   327  region = us-west-2
   328  s3 =`)),
   329  			expectedStack: []AST{
   330  				newCompletedSectionStatement(
   331  					defaultProfileStmt,
   332  				),
   333  				newExprStatement(noQuotesRegionEQRegion),
   334  			},
   335  		},
   336  		{
   337  			name: "token seperators [ and  ] in values",
   338  			r: bytes.NewBuffer([]byte(
   339  				`[default]
   340  sepInValue = =:[foo]]bar[
   341  output = json
   342  [assumerole]
   343  sepInValue==:[foo]]bar[
   344  output = json
   345  `)),
   346  			expectedStack: []AST{
   347  				newCompletedSectionStatement(defaultProfileStmt),
   348  				newExprStatement(sepInValueExpr),
   349  				newExprStatement(outputEQExpr),
   350  				newCompletedSectionStatement(assumeProfileStmt),
   351  				newExprStatement(sepInValueExpr),
   352  				newExprStatement(outputEQExpr),
   353  			},
   354  		},
   355  	}
   356  
   357  	for i, c := range cases {
   358  		t.Run(c.name, func(t *testing.T) {
   359  			stack, err := ParseAST(c.r)
   360  
   361  			if e, a := c.expectedError, err != nil; e != a {
   362  				t.Errorf("%d: expected %t, but received %t with error %v", i, e, a, err)
   363  			}
   364  
   365  			if e, a := len(c.expectedStack), len(stack); e != a {
   366  				t.Errorf("expected same length %d, but received %d", e, a)
   367  			}
   368  
   369  			if e, a := c.expectedStack, stack; !reflect.DeepEqual(e, a) {
   370  				buf := bytes.Buffer{}
   371  				buf.WriteString("expected:\n")
   372  				for j := 0; j < len(e); j++ {
   373  					buf.WriteString(fmt.Sprintf("\t%d: %v\n", j, e[j]))
   374  				}
   375  
   376  				buf.WriteString("\nreceived:\n")
   377  				for j := 0; j < len(a); j++ {
   378  					buf.WriteString(fmt.Sprintf("\t%d: %v\n", j, a[j]))
   379  				}
   380  
   381  				t.Errorf("%s", buf.String())
   382  			}
   383  		})
   384  	}
   385  }