Optimize slow bottleneck test of DockerHubPullSuite.TestPullNonExistingImage.
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"regexp" |
| 6 | 6 |
"strings" |
| 7 |
+ "sync" |
|
| 7 | 8 |
"time" |
| 8 | 9 |
|
| 9 | 10 |
"github.com/docker/distribution/digest" |
| ... | ... |
@@ -39,30 +40,68 @@ func (s *DockerHubPullSuite) TestPullFromCentralRegistry(c *check.C) {
|
| 39 | 39 |
// combinations of implicit tag and library prefix. |
| 40 | 40 |
func (s *DockerHubPullSuite) TestPullNonExistingImage(c *check.C) {
|
| 41 | 41 |
testRequires(c, DaemonIsLinux) |
| 42 |
- for _, e := range []struct {
|
|
| 42 |
+ |
|
| 43 |
+ type entry struct {
|
|
| 43 | 44 |
Repo string |
| 44 | 45 |
Alias string |
| 45 |
- }{
|
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ entries := []entry{
|
|
| 46 | 49 |
{"library/asdfasdf", "asdfasdf:foobar"},
|
| 47 | 50 |
{"library/asdfasdf", "library/asdfasdf:foobar"},
|
| 48 | 51 |
{"library/asdfasdf", "asdfasdf"},
|
| 49 | 52 |
{"library/asdfasdf", "asdfasdf:latest"},
|
| 50 | 53 |
{"library/asdfasdf", "library/asdfasdf"},
|
| 51 | 54 |
{"library/asdfasdf", "library/asdfasdf:latest"},
|
| 52 |
- } {
|
|
| 53 |
- out, err := s.CmdWithError("pull", e.Alias)
|
|
| 54 |
- c.Assert(err, checker.NotNil, check.Commentf("expected non-zero exit status when pulling non-existing image: %s", out))
|
|
| 55 |
- // Hub returns 401 rather than 404 for nonexistent repos over |
|
| 56 |
- // the v2 protocol - but we should end up falling back to v1, |
|
| 57 |
- // which does return a 404. |
|
| 58 |
- c.Assert(out, checker.Contains, fmt.Sprintf("Error: image %s not found", e.Repo), check.Commentf("expected image not found error messages"))
|
|
| 59 |
- |
|
| 60 |
- // pull -a on a nonexistent registry should fall back as well |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ // The option field indicates "-a" or not. |
|
| 58 |
+ type record struct {
|
|
| 59 |
+ e entry |
|
| 60 |
+ option string |
|
| 61 |
+ out string |
|
| 62 |
+ err error |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ // Execute 'docker pull' in parallel, pass results (out, err) and |
|
| 66 |
+ // necessary information ("-a" or not, and the image name) to channel.
|
|
| 67 |
+ var group sync.WaitGroup |
|
| 68 |
+ recordChan := make(chan record, len(entries)*2) |
|
| 69 |
+ for _, e := range entries {
|
|
| 70 |
+ group.Add(1) |
|
| 71 |
+ go func(e entry) {
|
|
| 72 |
+ defer group.Done() |
|
| 73 |
+ out, err := s.CmdWithError("pull", e.Alias)
|
|
| 74 |
+ recordChan <- record{e, "", out, err}
|
|
| 75 |
+ }(e) |
|
| 61 | 76 |
if !strings.ContainsRune(e.Alias, ':') {
|
| 62 |
- out, err := s.CmdWithError("pull", "-a", e.Alias)
|
|
| 63 |
- c.Assert(err, checker.NotNil, check.Commentf("expected non-zero exit status when pulling non-existing image: %s", out))
|
|
| 64 |
- c.Assert(out, checker.Contains, fmt.Sprintf("Error: image %s not found", e.Repo), check.Commentf("expected image not found error messages"))
|
|
| 65 |
- c.Assert(out, checker.Not(checker.Contains), "unauthorized", check.Commentf(`message should not contain "unauthorized"`)) |
|
| 77 |
+ // pull -a on a nonexistent registry should fall back as well |
|
| 78 |
+ group.Add(1) |
|
| 79 |
+ go func(e entry) {
|
|
| 80 |
+ defer group.Done() |
|
| 81 |
+ out, err := s.CmdWithError("pull", "-a", e.Alias)
|
|
| 82 |
+ recordChan <- record{e, "-a", out, err}
|
|
| 83 |
+ }(e) |
|
| 84 |
+ } |
|
| 85 |
+ } |
|
| 86 |
+ |
|
| 87 |
+ // Wait for completion |
|
| 88 |
+ group.Wait() |
|
| 89 |
+ close(recordChan) |
|
| 90 |
+ |
|
| 91 |
+ // Process the results (out, err). |
|
| 92 |
+ for record := range recordChan {
|
|
| 93 |
+ if len(record.option) == 0 {
|
|
| 94 |
+ c.Assert(record.err, checker.NotNil, check.Commentf("expected non-zero exit status when pulling non-existing image: %s", record.out))
|
|
| 95 |
+ // Hub returns 401 rather than 404 for nonexistent repos over |
|
| 96 |
+ // the v2 protocol - but we should end up falling back to v1, |
|
| 97 |
+ // which does return a 404. |
|
| 98 |
+ c.Assert(record.out, checker.Contains, fmt.Sprintf("Error: image %s not found", record.e.Repo), check.Commentf("expected image not found error messages"))
|
|
| 99 |
+ } else {
|
|
| 100 |
+ // pull -a on a nonexistent registry should fall back as well |
|
| 101 |
+ c.Assert(record.err, checker.NotNil, check.Commentf("expected non-zero exit status when pulling non-existing image: %s", record.out))
|
|
| 102 |
+ c.Assert(record.out, checker.Contains, fmt.Sprintf("Error: image %s not found", record.e.Repo), check.Commentf("expected image not found error messages"))
|
|
| 103 |
+ c.Assert(record.out, checker.Not(checker.Contains), "unauthorized", check.Commentf(`message should not contain "unauthorized"`)) |
|
| 66 | 104 |
} |
| 67 | 105 |
} |
| 68 | 106 |
|