OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // adapted from github.com/golang/appengine/datastore | 5 // adapted from github.com/golang/appengine/datastore |
6 | 6 |
7 package datastore | 7 package datastore |
8 | 8 |
9 import ( | 9 import ( |
| 10 "bytes" |
10 "fmt" | 11 "fmt" |
| 12 "io/ioutil" |
| 13 "os" |
| 14 "path/filepath" |
| 15 "runtime" |
11 "testing" | 16 "testing" |
12 | 17 |
13 "github.com/luci/gae/service/info" | 18 "github.com/luci/gae/service/info" |
14 "github.com/luci/luci-go/common/errors" | 19 "github.com/luci/luci-go/common/errors" |
15 . "github.com/luci/luci-go/common/testing/assertions" | 20 . "github.com/luci/luci-go/common/testing/assertions" |
16 . "github.com/smartystreets/goconvey/convey" | 21 . "github.com/smartystreets/goconvey/convey" |
17 "golang.org/x/net/context" | 22 "golang.org/x/net/context" |
18 ) | 23 ) |
19 | 24 |
20 func fakeDatastoreFactory(c context.Context, wantTxn bool) RawInterface { | 25 func fakeDatastoreFactory(c context.Context, wantTxn bool) RawInterface { |
(...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 Convey("extra field with bad type", func() { | 1289 Convey("extra field with bad type", func() { |
1285 type Bad struct { | 1290 type Bad struct { |
1286 A int64 `gae:",extra"` | 1291 A int64 `gae:",extra"` |
1287 } | 1292 } |
1288 So(func() { GetPLS(&Bad{}) }, ShouldPanicLike, | 1293 So(func() { GetPLS(&Bad{}) }, ShouldPanicLike, |
1289 "struct 'extra' field has invalid type i
nt64") | 1294 "struct 'extra' field has invalid type i
nt64") |
1290 }) | 1295 }) |
1291 }) | 1296 }) |
1292 }) | 1297 }) |
1293 } | 1298 } |
| 1299 |
| 1300 func TestParseIndexYAML(t *testing.T) { |
| 1301 t.Parallel() |
| 1302 |
| 1303 Convey("parses properly formatted YAML", t, func() { |
| 1304 yaml := ` |
| 1305 indexes: |
| 1306 |
| 1307 - kind: Cat |
| 1308 ancestor: no |
| 1309 properties: |
| 1310 - name: name |
| 1311 - name: age |
| 1312 direction: desc |
| 1313 |
| 1314 - kind: Cat |
| 1315 properties: |
| 1316 - name: name |
| 1317 direction: asc |
| 1318 - name: whiskers |
| 1319 direction: desc |
| 1320 |
| 1321 - kind: Store |
| 1322 ancestor: yes |
| 1323 properties: |
| 1324 - name: business |
| 1325 direction: asc |
| 1326 - name: owner |
| 1327 direction: asc |
| 1328 ` |
| 1329 ids, err := ParseIndexYAML(bytes.NewBuffer([]byte(yaml))) |
| 1330 So(err, ShouldBeNil) |
| 1331 |
| 1332 expected := []*IndexDefinition{ |
| 1333 { |
| 1334 Kind: "Cat", |
| 1335 Ancestor: false, |
| 1336 SortBy: []IndexColumn{ |
| 1337 { |
| 1338 Property: "name", |
| 1339 Descending: false, |
| 1340 }, |
| 1341 { |
| 1342 Property: "age", |
| 1343 Descending: true, |
| 1344 }, |
| 1345 }, |
| 1346 }, |
| 1347 { |
| 1348 Kind: "Cat", |
| 1349 Ancestor: false, |
| 1350 SortBy: []IndexColumn{ |
| 1351 { |
| 1352 Property: "name", |
| 1353 Descending: false, |
| 1354 }, |
| 1355 { |
| 1356 Property: "whiskers", |
| 1357 Descending: true, |
| 1358 }, |
| 1359 }, |
| 1360 }, |
| 1361 { |
| 1362 Kind: "Store", |
| 1363 Ancestor: true, |
| 1364 SortBy: []IndexColumn{ |
| 1365 { |
| 1366 Property: "business", |
| 1367 Descending: false, |
| 1368 }, |
| 1369 { |
| 1370 Property: "owner", |
| 1371 Descending: false, |
| 1372 }, |
| 1373 }, |
| 1374 }, |
| 1375 } |
| 1376 So(ids, ShouldResembleV, expected) |
| 1377 }) |
| 1378 |
| 1379 Convey("returns non-nil error for incorrectly formatted YAML", t, func()
{ |
| 1380 |
| 1381 Convey("missing top level `indexes` key", func() { |
| 1382 yaml := ` |
| 1383 - kind: Cat |
| 1384 properties: |
| 1385 - name: name |
| 1386 - name: age |
| 1387 direction: desc |
| 1388 ` |
| 1389 _, err := ParseIndexYAML(bytes.NewBuffer([]byte(yaml))) |
| 1390 So(err, ShouldNotBeNil) |
| 1391 }) |
| 1392 |
| 1393 Convey("missing `name` key in property", func() { |
| 1394 yaml := ` |
| 1395 indexes: |
| 1396 |
| 1397 - kind: Cat |
| 1398 ancestor: no |
| 1399 properties: |
| 1400 - name: name |
| 1401 - direction: desc |
| 1402 ` |
| 1403 _, err := ParseIndexYAML(bytes.NewBuffer([]byte(yaml))) |
| 1404 So(err, ShouldNotBeNil) |
| 1405 }) |
| 1406 }) |
| 1407 } |
| 1408 |
| 1409 func TestFindAndParseIndexYAML(t *testing.T) { |
| 1410 t.Parallel() |
| 1411 |
| 1412 Convey("returns parsed index definitions for existing index YAML files",
t, func() { |
| 1413 // YAML content to write temporarily to disk |
| 1414 yaml1 := ` |
| 1415 indexes: |
| 1416 |
| 1417 - kind: Test Same Level |
| 1418 properties: |
| 1419 - name: name |
| 1420 - name: age |
| 1421 direction: desc |
| 1422 ` |
| 1423 yaml2 := ` |
| 1424 indexes: |
| 1425 |
| 1426 - kind: Test Higher Level |
| 1427 properties: |
| 1428 - name: name |
| 1429 - name: age |
| 1430 direction: desc |
| 1431 |
| 1432 - kind: Test Foo |
| 1433 properties: |
| 1434 - name: height |
| 1435 - name: weight |
| 1436 direction: asc |
| 1437 ` |
| 1438 // determine the directory of this test file |
| 1439 _, path, _, ok := runtime.Caller(0) |
| 1440 if !ok { |
| 1441 panic(fmt.Errorf("failed to determine test file path")) |
| 1442 } |
| 1443 sameLevelDir := filepath.Dir(path) |
| 1444 |
| 1445 Convey("picks YAML file at same level as test file instead of hi
gher level YAML file", func() { |
| 1446 writePath1 := filepath.Join(sameLevelDir, "index.yml") |
| 1447 writePath2 := filepath.Join(filepath.Dir(sameLevelDir),
"index.yaml") |
| 1448 |
| 1449 setup := func() { |
| 1450 ioutil.WriteFile(writePath1, []byte(yaml1), 0600
) |
| 1451 ioutil.WriteFile(writePath2, []byte(yaml2), 0600
) |
| 1452 } |
| 1453 |
| 1454 cleanup := func() { |
| 1455 os.Remove(writePath1) |
| 1456 os.Remove(writePath2) |
| 1457 } |
| 1458 |
| 1459 setup() |
| 1460 defer cleanup() |
| 1461 ids, err := FindAndParseIndexYAML(".") |
| 1462 So(err, ShouldBeNil) |
| 1463 So(ids[0].Kind, ShouldEqual, "Test Same Level") |
| 1464 }) |
| 1465 |
| 1466 Convey("finds YAML file two levels up given an empty relative pa
th", func() { |
| 1467 writePath := filepath.Join(filepath.Dir(filepath.Dir(sam
eLevelDir)), "index.yaml") |
| 1468 |
| 1469 setup := func() { |
| 1470 ioutil.WriteFile(writePath, []byte(yaml2), 0600) |
| 1471 } |
| 1472 |
| 1473 cleanup := func() { |
| 1474 os.Remove(writePath) |
| 1475 } |
| 1476 |
| 1477 setup() |
| 1478 defer cleanup() |
| 1479 ids, err := FindAndParseIndexYAML("") |
| 1480 So(err, ShouldBeNil) |
| 1481 So(ids[1].Kind, ShouldEqual, "Test Foo") |
| 1482 }) |
| 1483 |
| 1484 Convey("finds YAML file given a relative path", func() { |
| 1485 writeDir, err := ioutil.TempDir(filepath.Dir(sameLevelDi
r), "temp-test-datastore-") |
| 1486 if err != nil { |
| 1487 panic(err) |
| 1488 } |
| 1489 writePath := filepath.Join(writeDir, "index.yml") |
| 1490 |
| 1491 setup := func() { |
| 1492 ioutil.WriteFile(writePath, []byte(yaml2), 0600) |
| 1493 } |
| 1494 |
| 1495 cleanup := func() { |
| 1496 os.RemoveAll(writeDir) |
| 1497 } |
| 1498 |
| 1499 setup() |
| 1500 defer cleanup() |
| 1501 ids, err := FindAndParseIndexYAML(filepath.Join("..", fi
lepath.Base(writeDir))) |
| 1502 So(err, ShouldBeNil) |
| 1503 So(ids[1].Kind, ShouldEqual, "Test Foo") |
| 1504 }) |
| 1505 |
| 1506 Convey("finds YAML file given an absolute path", func() { |
| 1507 writePath := filepath.Join(sameLevelDir, "index.yaml") |
| 1508 |
| 1509 setup := func() { |
| 1510 ioutil.WriteFile(writePath, []byte(yaml2), 0600) |
| 1511 } |
| 1512 |
| 1513 cleanup := func() { |
| 1514 os.Remove(writePath) |
| 1515 } |
| 1516 |
| 1517 setup() |
| 1518 defer cleanup() |
| 1519 |
| 1520 abs, err := filepath.Abs(sameLevelDir) |
| 1521 if err != nil { |
| 1522 panic(fmt.Errorf("failed to find absolute path f
or `%s`", sameLevelDir)) |
| 1523 } |
| 1524 |
| 1525 ids, err := FindAndParseIndexYAML(abs) |
| 1526 So(err, ShouldBeNil) |
| 1527 So(ids[1].Kind, ShouldEqual, "Test Foo") |
| 1528 }) |
| 1529 }) |
| 1530 } |
OLD | NEW |