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 }