OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package config |
| 6 |
| 7 import ( |
| 8 "sync" |
| 9 "testing" |
| 10 "time" |
| 11 |
| 12 "github.com/golang/protobuf/proto" |
| 13 "github.com/luci/luci-go/common/clock" |
| 14 "github.com/luci/luci-go/common/clock/testclock" |
| 15 "github.com/luci/luci-go/common/config/impl/memory" |
| 16 "github.com/luci/luci-go/logdog/api/config/svcconfig" |
| 17 "github.com/luci/luci-go/luci_config/server/cfgclient/backend/testconfig
" |
| 18 |
| 19 "golang.org/x/net/context" |
| 20 |
| 21 . "github.com/smartystreets/goconvey/convey" |
| 22 ) |
| 23 |
| 24 func TestPoller(t *testing.T) { |
| 25 t.Parallel() |
| 26 |
| 27 Convey(`Using in-memory configuration manager options`, t, func() { |
| 28 c := context.Background() |
| 29 c, tc := testclock.UseTime(c, testclock.TestTimeLocal) |
| 30 |
| 31 // In-memory configuration service. |
| 32 cfg := &svcconfig.Config{ |
| 33 Transport: &svcconfig.Transport{ |
| 34 Type: &svcconfig.Transport_Pubsub{ |
| 35 Pubsub: &svcconfig.Transport_PubSub{ |
| 36 Project: "foo", |
| 37 Topic: "bar", |
| 38 Subscription: "baz", |
| 39 }, |
| 40 }, |
| 41 }, |
| 42 } |
| 43 cset := memory.ConfigSet{ |
| 44 "test-configuration.cfg": proto.MarshalTextString(cfg), |
| 45 } |
| 46 |
| 47 mc := memory.New(map[string]memory.ConfigSet{ |
| 48 "svcconfig/logdog/test": cset, |
| 49 }) |
| 50 c = testconfig.WithCommonClient(c, mc) |
| 51 |
| 52 p := ChangePoller{ |
| 53 ConfigSet: "svcconfig/logdog/test", |
| 54 Path: "test-configuration.cfg", |
| 55 } |
| 56 So(p.Refresh(c), ShouldBeNil) |
| 57 initHash := p.ContentHash |
| 58 |
| 59 Convey(`With an OnChange function installed.`, func() { |
| 60 changeDetectedC := make(chan bool, 1) |
| 61 p.Period = time.Second |
| 62 p.OnChange = func() { |
| 63 changeDetectedC <- true |
| 64 } |
| 65 |
| 66 timeAdvanceC := make(chan time.Duration) |
| 67 tc.SetTimerCallback(func(time.Duration, clock.Timer) { |
| 68 t, ok := <-timeAdvanceC |
| 69 if ok { |
| 70 tc.Add(t) |
| 71 } |
| 72 }) |
| 73 |
| 74 c, cancelFunc := context.WithCancel(c) |
| 75 |
| 76 doneC := make(chan struct{}) |
| 77 go func() { |
| 78 p.Run(c) |
| 79 close(doneC) |
| 80 }() |
| 81 |
| 82 var shutdownOnce sync.Once |
| 83 shutdown := func() { |
| 84 shutdownOnce.Do(func() { |
| 85 cancelFunc() |
| 86 close(timeAdvanceC) |
| 87 <-doneC |
| 88 }) |
| 89 } |
| 90 defer shutdown() |
| 91 |
| 92 Convey(`When the configuration changes`, func() { |
| 93 cfg.Transport.GetPubsub().Project = "qux" |
| 94 cset[string(p.Path)] = proto.MarshalTextString(c
fg) |
| 95 |
| 96 Convey(`Will execute the OnChange function if th
e configuration changes.`, func() { |
| 97 timeAdvanceC <- time.Second |
| 98 So(<-changeDetectedC, ShouldBeTrue) |
| 99 So(p.ContentHash, ShouldNotEqual, initHa
sh) |
| 100 }) |
| 101 }) |
| 102 |
| 103 Convey(`Will do nothing if the configuration doesn't cha
nge.`, func() { |
| 104 // Advancing time twice ensures that the poll lo
op has processed at |
| 105 // least one non-changing reload. |
| 106 timeAdvanceC <- time.Second |
| 107 timeAdvanceC <- time.Second |
| 108 |
| 109 changeDetected := false |
| 110 select { |
| 111 case <-changeDetectedC: |
| 112 changeDetected = true |
| 113 default: |
| 114 } |
| 115 So(changeDetected, ShouldBeFalse) |
| 116 |
| 117 shutdown() |
| 118 So(p.ContentHash, ShouldEqual, initHash) |
| 119 }) |
| 120 }) |
| 121 }) |
| 122 } |
OLD | NEW |