OLD | NEW |
1 package store_test | 1 package store_test |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
5 "io" | 5 "io" |
6 "io/ioutil" | 6 "io/ioutil" |
7 . "launchpad.net/gocheck" | 7 . "launchpad.net/gocheck" |
8 "launchpad.net/juju/go/charm" | 8 "launchpad.net/juju/go/charm" |
9 "launchpad.net/juju/go/log" | 9 "launchpad.net/juju/go/log" |
10 "launchpad.net/juju/go/store" | 10 "launchpad.net/juju/go/store" |
11 "launchpad.net/mgo/bson" | 11 "launchpad.net/mgo/bson" |
12 "path/filepath" | 12 "path/filepath" |
| 13 "strconv" |
13 "testing" | 14 "testing" |
14 "time" | 15 "time" |
15 ) | 16 ) |
16 | 17 |
17 func Test(t *testing.T) { | 18 func Test(t *testing.T) { |
18 TestingT(t) | 19 TestingT(t) |
19 } | 20 } |
20 | 21 |
21 var _ = Suite(&StoreSuite{}) | 22 var _ = Suite(&StoreSuite{}) |
22 var _ = Suite(&TrivialSuite{}) | 23 var _ = Suite(&TrivialSuite{}) |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 // Same digest bumps revision because one of them was old. | 333 // Same digest bumps revision because one of them was old. |
333 pub, err = s.store.CharmPublisher(urls, "digest-1") | 334 pub, err = s.store.CharmPublisher(urls, "digest-1") |
334 c.Assert(err, IsNil) | 335 c.Assert(err, IsNil) |
335 c.Assert(pub.Revision(), Equals, 2) | 336 c.Assert(pub.Revision(), Equals, 2) |
336 err = pub.Publish(&FakeCharmDir{}) | 337 err = pub.Publish(&FakeCharmDir{}) |
337 c.Assert(err, IsNil) | 338 c.Assert(err, IsNil) |
338 } | 339 } |
339 | 340 |
340 const fakeRevZeroSha = "319095521ac8a62fa1e8423351973512ecca8928c9f62025e37de57c
9ef07a53" | 341 const fakeRevZeroSha = "319095521ac8a62fa1e8423351973512ecca8928c9f62025e37de57c
9ef07a53" |
341 | 342 |
342 func (s *StoreSuite) TestBundleSha256(c *C) { | 343 func (s *StoreSuite) TestCharmBundleData(c *C) { |
343 url := charm.MustParseURL("cs:oneiric/wordpress") | 344 url := charm.MustParseURL("cs:oneiric/wordpress") |
344 urls := []*charm.URL{url} | 345 urls := []*charm.URL{url} |
345 | 346 |
346 pub, err := s.store.CharmPublisher(urls, "key") | 347 pub, err := s.store.CharmPublisher(urls, "key") |
347 c.Assert(err, IsNil) | 348 c.Assert(err, IsNil) |
348 c.Assert(pub.Revision(), Equals, 0) | 349 c.Assert(pub.Revision(), Equals, 0) |
349 | 350 |
350 err = pub.Publish(&FakeCharmDir{}) | 351 err = pub.Publish(&FakeCharmDir{}) |
351 c.Assert(err, IsNil) | 352 c.Assert(err, IsNil) |
352 | 353 |
353 info, rc, err := s.store.OpenCharm(url) | 354 info, rc, err := s.store.OpenCharm(url) |
354 c.Assert(err, IsNil) | 355 c.Assert(err, IsNil) |
355 c.Check(info.BundleSha256(), Equals, fakeRevZeroSha) | 356 c.Check(info.BundleSha256(), Equals, fakeRevZeroSha) |
| 357 c.Check(info.BundleSize(), Equals, int64(len("charm-revision-0"))) |
356 err = rc.Close() | 358 err = rc.Close() |
357 c.Check(err, IsNil) | 359 c.Check(err, IsNil) |
358 } | 360 } |
359 | 361 |
360 func (s *StoreSuite) TestLogCharmEventWithRevisionedURL(c *C) { | 362 func (s *StoreSuite) TestLogCharmEventWithRevisionedURL(c *C) { |
361 url := charm.MustParseURL("cs:oneiric/wordpress-0") | 363 url := charm.MustParseURL("cs:oneiric/wordpress-0") |
362 event := &store.CharmEvent{ | 364 event := &store.CharmEvent{ |
363 Kind: store.EventPublishError, | 365 Kind: store.EventPublishError, |
364 Digest: "some-digest", | 366 Digest: "some-digest", |
365 URLs: []*charm.URL{url}, | 367 URLs: []*charm.URL{url}, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 | 435 |
434 event, err = s.store.CharmEvent(urls[1], "revKey1") | 436 event, err = s.store.CharmEvent(urls[1], "revKey1") |
435 c.Assert(err, IsNil) | 437 c.Assert(err, IsNil) |
436 c.Assert(event, DeepEquals, event1) | 438 c.Assert(event, DeepEquals, event1) |
437 | 439 |
438 event, err = s.store.CharmEvent(urls[1], "revKeyX") | 440 event, err = s.store.CharmEvent(urls[1], "revKeyX") |
439 c.Assert(err, Equals, store.ErrNotFound) | 441 c.Assert(err, Equals, store.ErrNotFound) |
440 c.Assert(event, IsNil) | 442 c.Assert(event, IsNil) |
441 } | 443 } |
442 | 444 |
| 445 func (s *StoreSuite) TestCounters(c *C) { |
| 446 sum, err := s.store.SumCounter([]string{"a"}, false) |
| 447 c.Assert(err, IsNil) |
| 448 c.Assert(sum, Equals, int64(0)) |
| 449 |
| 450 for i := 0; i < 10; i++ { |
| 451 err := s.store.IncCounter([]string{"a", "b", "c"}) |
| 452 c.Assert(err, IsNil) |
| 453 } |
| 454 for i := 0; i < 7; i++ { |
| 455 s.store.IncCounter([]string{"a", "b"}) |
| 456 c.Assert(err, IsNil) |
| 457 } |
| 458 for i := 0; i < 3; i++ { |
| 459 s.store.IncCounter([]string{"a", "z", "b"}) |
| 460 c.Assert(err, IsNil) |
| 461 } |
| 462 |
| 463 tests := []struct { |
| 464 key []string |
| 465 prefix bool |
| 466 result int64 |
| 467 }{ |
| 468 {[]string{"a", "b", "c"}, false, 10}, |
| 469 {[]string{"a", "b"}, false, 7}, |
| 470 {[]string{"a", "z", "b"}, false, 3}, |
| 471 {[]string{"a", "b", "c"}, true, 10}, |
| 472 {[]string{"a", "b"}, true, 17}, |
| 473 {[]string{"a"}, true, 20}, |
| 474 {[]string{"b"}, true, 0}, |
| 475 } |
| 476 |
| 477 for _, t := range tests { |
| 478 c.Logf("Test: %#v\n", t) |
| 479 sum, err := s.store.SumCounter(t.key, t.prefix) |
| 480 c.Assert(err, IsNil) |
| 481 c.Assert(sum, Equals, t.result) |
| 482 } |
| 483 |
| 484 // High-level interface works. Now check that the data is |
| 485 // stored correctly. |
| 486 counters := s.Session.DB("juju").C("stat.counters") |
| 487 docs1, err := counters.Count() |
| 488 c.Assert(err, IsNil) |
| 489 if docs1 != 3 && docs1 != 4 { |
| 490 fmt.Errorf("Expected 3 or 4 docs in counters collection, got %d"
, docs1) |
| 491 } |
| 492 |
| 493 // Hack times so that the next operation adds another document. |
| 494 err = counters.Update(nil, bson.D{{"$set", bson.D{{"t", 1}}}}) |
| 495 c.Check(err, IsNil) |
| 496 |
| 497 err = s.store.IncCounter([]string{"a", "b", "c"}) |
| 498 c.Assert(err, IsNil) |
| 499 |
| 500 docs2, err := counters.Count() |
| 501 c.Assert(err, IsNil) |
| 502 c.Assert(docs2, Equals, docs1+1) |
| 503 |
| 504 sum, err = s.store.SumCounter([]string{"a", "b", "c"}, false) |
| 505 c.Assert(err, IsNil) |
| 506 c.Assert(sum, Equals, int64(11)) |
| 507 |
| 508 sum, err = s.store.SumCounter([]string{"a"}, true) |
| 509 c.Assert(err, IsNil) |
| 510 c.Assert(sum, Equals, int64(21)) |
| 511 } |
| 512 |
| 513 func (s *StoreSuite) TestCountersReadOnlySum(c *C) { |
| 514 // Summing up an unknown key shouldn't add the key to the database. |
| 515 sum, err := s.store.SumCounter([]string{"a", "b", "c"}, false) |
| 516 c.Assert(err, IsNil) |
| 517 c.Assert(sum, Equals, int64(0)) |
| 518 |
| 519 tokens := s.Session.DB("juju").C("stat.tokens") |
| 520 n, err := tokens.Count() |
| 521 c.Assert(err, IsNil) |
| 522 c.Assert(n, Equals, 0) |
| 523 } |
| 524 |
| 525 func (s *StoreSuite) TestCountersTokenCaching(c *C) { |
| 526 sum, err := s.store.SumCounter([]string{"a"}, false) |
| 527 c.Assert(err, IsNil) |
| 528 c.Assert(sum, Equals, int64(0)) |
| 529 |
| 530 const genSize = 512 |
| 531 |
| 532 // All of these will be cached, as we have two generations |
| 533 // of genSize entries each. |
| 534 for i := 0; i < genSize*2; i++ { |
| 535 err := s.store.IncCounter([]string{strconv.Itoa(i)}) |
| 536 c.Assert(err, IsNil) |
| 537 } |
| 538 |
| 539 // Now go behind the scenes and corrupt all the tokens. |
| 540 tokens := s.Session.DB("juju").C("stat.tokens") |
| 541 err = tokens.UpdateAll(nil, bson.M{"$set": bson.M{"t": "corrupted"}}) |
| 542 c.Assert(err, IsNil) |
| 543 |
| 544 // We can consult the counters for the cached entries still. |
| 545 // First, check that the newest generation is good. |
| 546 for i := genSize; i < genSize*2; i++ { |
| 547 n, err := s.store.SumCounter([]string{strconv.Itoa(i)}, false) |
| 548 c.Assert(err, IsNil) |
| 549 c.Assert(n, Equals, int64(1)) |
| 550 } |
| 551 |
| 552 // Now, we can still access a single entry of the older generation, |
| 553 // but this will cause the generations to flip and thus the rest |
| 554 // of the old generation will go away as the top half of the |
| 555 // entries is turned into the old generation. |
| 556 n, err := s.store.SumCounter([]string{"0"}, false) |
| 557 c.Assert(err, IsNil) |
| 558 c.Assert(n, Equals, int64(1)) |
| 559 |
| 560 // Now we've lost access to the rest of the old generation. |
| 561 for i := 1; i < genSize; i++ { |
| 562 n, err := s.store.SumCounter([]string{strconv.Itoa(i)}, false) |
| 563 c.Assert(err, IsNil) |
| 564 c.Assert(n, Equals, int64(0)) |
| 565 } |
| 566 |
| 567 // But we still have all of the top half available since it was |
| 568 // moved into the old generation. |
| 569 for i := genSize; i < genSize*2; i++ { |
| 570 n, err := s.store.SumCounter([]string{strconv.Itoa(i)}, false) |
| 571 c.Assert(err, IsNil) |
| 572 c.Assert(n, Equals, int64(1)) |
| 573 } |
| 574 } |
| 575 |
443 func (s *TrivialSuite) TestEventString(c *C) { | 576 func (s *TrivialSuite) TestEventString(c *C) { |
444 c.Assert(store.EventPublished, Matches, "published") | 577 c.Assert(store.EventPublished, Matches, "published") |
445 c.Assert(store.EventPublishError, Matches, "publish-error") | 578 c.Assert(store.EventPublishError, Matches, "publish-error") |
446 for kind := store.CharmEventKind(1); kind < store.EventKindCount; kind++
{ | 579 for kind := store.CharmEventKind(1); kind < store.EventKindCount; kind++
{ |
447 // This guarantees the switch in String is properly | 580 // This guarantees the switch in String is properly |
448 // updated with new event kinds. | 581 // updated with new event kinds. |
449 c.Assert(kind.String(), Matches, "[a-z-]+") | 582 c.Assert(kind.String(), Matches, "[a-z-]+") |
450 } | 583 } |
451 } | 584 } |
OLD | NEW |