示例#1
0
func (*StringForwarderSuite) TestMessagesDroppedWhenBusy(c *gc.C) {
	var messages []string
	received := make(chan struct{}, 10)
	next := make(chan struct{})
	blockingCallback := func(msg string) {
		waitFor(c, next)
		messages = append(messages, msg)
		sendEvent(c, received)
	}
	forwarder := stringforwarder.New(blockingCallback)
	forwarder.Forward("first")
	forwarder.Forward("second")
	forwarder.Forward("third")
	// At this point we should have started processing "first", but the
	// other two messages are dropped.
	sendEvent(c, next)
	waitFor(c, received)
	// now we should be ready to get another message
	forwarder.Forward("fourth")
	forwarder.Forward("fifth")
	// finish fourth
	sendEvent(c, next)
	waitFor(c, received)
	dropCount := forwarder.Stop()
	c.Check(messages, gc.DeepEquals, []string{"first", "fourth"})
	c.Check(dropCount, gc.Equals, uint64(3))
}
示例#2
0
func (*StringForwarderSuite) TestRace(c *gc.C) {
	forwarder := stringforwarder.New(noopCallback)
	stop := make(chan struct{})
	wg := &sync.WaitGroup{}
	f := func(wg *sync.WaitGroup) {
		wg.Done()
		for {
			select {
			case <-stop:
				return
			default:
				forwarder.Forward("next message")
			}
		}
	}
	for i := 0; i < 4; i++ {
		wg.Add(1)
		go f(wg)
	}
	wg.Wait()
	time.Sleep(10 * time.Millisecond)
	close(stop)
	count := forwarder.Stop()
	c.Check(count, jc.GreaterThan, uint64(0))
}
示例#3
0
func (*StringForwarderSuite) TestAllDroppedWithNoCallback(c *gc.C) {
	forwarder := stringforwarder.New(nil)
	forwarder.Forward("one")
	forwarder.Forward("two")
	forwarder.Forward("three")
	c.Check(forwarder.Stop(), gc.Equals, uint64(3))
}
示例#4
0
func (*StringForwarderSuite) TestMessagesDroppedAfterStop(c *gc.C) {
	var messages []string
	forwarder := stringforwarder.New(func(msg string) {
		messages = append(messages, msg)
	})
	forwarder.Stop()
	forwarder.Forward("one")
	forwarder.Forward("two")
	forwarder.Stop()
	c.Check(messages, gc.HasLen, 0)
}
示例#5
0
func (*StringForwarderSuite) TestReceives(c *gc.C) {
	var messages []string
	received := make(chan struct{}, 10)
	forwarder := stringforwarder.New(func(msg string) {
		messages = append(messages, msg)
		received <- struct{}{}
	})
	forwarder.Forward("one")
	waitFor(c, received)
	c.Check(forwarder.Stop(), gc.Equals, uint64(0))
	c.Check(messages, gc.DeepEquals, []string{"one"})
}
示例#6
0
func (*StringForwarderSuite) TestSchedulerSensitivity(c *gc.C) {
	var wg sync.WaitGroup
	f := func() {
		defer wg.Done()
		forwarder := stringforwarder.New(noopCallback)
		forwarder.Forward("msg")
		n := forwarder.Stop()
		c.Check(n, gc.Equals, uint64(0))
	}
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go f()
	}
	wg.Wait()
}
示例#7
0
文件: client_image.go 项目: bac/juju
// EnsureImageExists makes sure we have a local image so we can launch a
// container.
// @param series: OS series (trusty, precise, etc)
// @param architecture: (TODO) The architecture of the image we want to use
// @param trustLocal: (TODO) check if we already have an image with the right alias.
// Setting this to False means we will always check the remote sources and only
// launch the newest version.
// @param sources: a list of Remotes that we will look in for the image.
// @param copyProgressHandler: a callback function. If we have to download an
// image, we will call this with messages indicating how much of the download
// we have completed (and where we are downloading it from).
func (i *imageClient) EnsureImageExists(series string, sources []Remote, copyProgressHandler func(string)) error {
	// TODO(jam) Find a way to test this, even though lxd.Client can't
	// really be stubbed out because CopyImage takes one directly and pokes
	// at private methods so we can't easily tweak it.
	name := i.ImageNameForSeries(series)

	lastErr := errors.New("image not imported!")
	for _, remote := range sources {
		source, err := i.connectToSource(remote)
		if err != nil {
			logger.Infof("failed to connect to %q: %s", remote.Host, err)
			lastErr = err
			continue
		}

		// TODO(jam): there are multiple possible spellings for aliases,
		// unfortunately. cloud-images only hosts ubuntu images, and
		// aliases them as "trusty" or "trusty/amd64" or
		// "trusty/amd64/20160304". However, we should be more
		// explicit. and use "ubuntu/trusty/amd64" as our default
		// naming scheme, and only fall back for synchronization.
		target := source.GetAlias(series)
		if target == "" {
			logger.Infof("no image for %s found in %s", name, source.URL())
			// TODO(jam) Add a test that we skip sources that don't
			// have what we are looking for
			continue
		}
		logger.Infof("found image from %s for %s = %s",
			source.URL(), series, target)
		forwarder := stringforwarder.New(copyProgressHandler)
		defer func() {
			dropCount := forwarder.Stop()
			logger.Debugf("dropped %d progress messages", dropCount)
		}()
		adapter := &progressContext{
			logger:  logger,
			level:   loggo.INFO,
			context: fmt.Sprintf("copying image for %s from %s: %%s", name, source.URL()),
			forward: forwarder.Forward,
		}
		err = source.CopyImage(series, i.raw, []string{name}, adapter.copyProgress)
		return errors.Annotatef(err, "unable to get LXD image for %s", name)
	}
	return lastErr
}
示例#8
0
func (*StringForwarderSuite) TestStopIsReentrant(c *gc.C) {
	forwarder := stringforwarder.New(noopCallback)
	forwarder.Stop()
	forwarder.Stop()
}