github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/environs/sync/sync_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package sync_test
     5  
     6  import (
     7  	"bytes"
     8  	"io"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"sort"
    15  	"testing"
    16  
    17  	gitjujutesting "github.com/juju/testing"
    18  	jc "github.com/juju/testing/checkers"
    19  	"github.com/juju/utils"
    20  	gc "launchpad.net/gocheck"
    21  
    22  	"github.com/juju/juju/environs"
    23  	"github.com/juju/juju/environs/config"
    24  	"github.com/juju/juju/environs/configstore"
    25  	"github.com/juju/juju/environs/filestorage"
    26  	"github.com/juju/juju/environs/simplestreams"
    27  	"github.com/juju/juju/environs/storage"
    28  	"github.com/juju/juju/environs/sync"
    29  	envtesting "github.com/juju/juju/environs/testing"
    30  	envtools "github.com/juju/juju/environs/tools"
    31  	toolstesting "github.com/juju/juju/environs/tools/testing"
    32  	"github.com/juju/juju/provider/dummy"
    33  	coretesting "github.com/juju/juju/testing"
    34  	coretools "github.com/juju/juju/tools"
    35  	"github.com/juju/juju/version"
    36  )
    37  
    38  func TestPackage(t *testing.T) {
    39  	gc.TestingT(t)
    40  }
    41  
    42  type syncSuite struct {
    43  	coretesting.FakeJujuHomeSuite
    44  	envtesting.ToolsFixture
    45  	targetEnv    environs.Environ
    46  	origVersion  version.Binary
    47  	storage      storage.Storage
    48  	localStorage string
    49  }
    50  
    51  var _ = gc.Suite(&syncSuite{})
    52  var _ = gc.Suite(&uploadSuite{})
    53  var _ = gc.Suite(&badBuildSuite{})
    54  
    55  func (s *syncSuite) setUpTest(c *gc.C) {
    56  	s.FakeJujuHomeSuite.SetUpTest(c)
    57  	s.ToolsFixture.SetUpTest(c)
    58  	s.origVersion = version.Current
    59  	// It's important that this be v1.8.x to match the test data.
    60  	version.Current.Number = version.MustParse("1.8.3")
    61  
    62  	// Create a target environments.yaml.
    63  	envConfig := `
    64  environments:
    65      test-target:
    66          type: dummy
    67          state-server: false
    68          authorized-keys: "not-really-one"
    69  `
    70  	coretesting.WriteEnvironments(c, envConfig)
    71  	var err error
    72  	s.targetEnv, err = environs.PrepareFromName("test-target", coretesting.Context(c), configstore.NewMem())
    73  	c.Assert(err, gc.IsNil)
    74  	envtesting.RemoveAllTools(c, s.targetEnv)
    75  
    76  	// Create a source storage.
    77  	baseDir := c.MkDir()
    78  	stor, err := filestorage.NewFileStorageWriter(baseDir)
    79  	c.Assert(err, gc.IsNil)
    80  	s.storage = stor
    81  
    82  	// Create a local tools directory.
    83  	s.localStorage = c.MkDir()
    84  
    85  	// Populate both local and default tools locations with the public tools.
    86  	versionStrings := make([]string, len(vAll))
    87  	for i, vers := range vAll {
    88  		versionStrings[i] = vers.String()
    89  	}
    90  	toolstesting.MakeTools(c, baseDir, "releases", versionStrings)
    91  	toolstesting.MakeTools(c, s.localStorage, "releases", versionStrings)
    92  
    93  	// Switch the default tools location.
    94  	baseURL, err := s.storage.URL(storage.BaseToolsPath)
    95  	c.Assert(err, gc.IsNil)
    96  	s.PatchValue(&envtools.DefaultBaseURL, baseURL)
    97  }
    98  
    99  func (s *syncSuite) tearDownTest(c *gc.C) {
   100  	dummy.Reset()
   101  	version.Current = s.origVersion
   102  	s.ToolsFixture.TearDownTest(c)
   103  	s.FakeJujuHomeSuite.TearDownTest(c)
   104  }
   105  
   106  var tests = []struct {
   107  	description   string
   108  	ctx           *sync.SyncContext
   109  	source        bool
   110  	tools         []version.Binary
   111  	version       version.Number
   112  	major         int
   113  	minor         int
   114  	expectMirrors bool
   115  }{
   116  	{
   117  		description: "copy newest from the filesystem",
   118  		ctx:         &sync.SyncContext{},
   119  		source:      true,
   120  		tools:       v180all,
   121  	},
   122  	{
   123  		description: "copy newest from the dummy environment",
   124  		ctx:         &sync.SyncContext{},
   125  		tools:       v180all,
   126  	},
   127  	{
   128  		description: "copy matching dev from the dummy environment",
   129  		ctx:         &sync.SyncContext{},
   130  		version:     version.MustParse("1.9.3"),
   131  		tools:       v190all,
   132  	},
   133  	{
   134  		description: "copy matching major, minor from the dummy environment",
   135  		ctx:         &sync.SyncContext{},
   136  		major:       3,
   137  		minor:       2,
   138  		tools:       []version.Binary{v320p64},
   139  	},
   140  	{
   141  		description: "copy matching major, minor dev from the dummy environment",
   142  		ctx:         &sync.SyncContext{},
   143  		major:       3,
   144  		minor:       1,
   145  		tools:       []version.Binary{v310p64},
   146  	},
   147  	{
   148  		description: "copy all from the dummy environment",
   149  		ctx: &sync.SyncContext{
   150  			AllVersions: true,
   151  		},
   152  		tools: v1noDev,
   153  	},
   154  	{
   155  		description: "copy all and dev from the dummy environment",
   156  		ctx: &sync.SyncContext{
   157  			AllVersions: true,
   158  			Dev:         true,
   159  		},
   160  		tools: v1all,
   161  	},
   162  	{
   163  		description: "write the mirrors files",
   164  		ctx: &sync.SyncContext{
   165  			Public: true,
   166  		},
   167  		tools:         v180all,
   168  		expectMirrors: true,
   169  	},
   170  }
   171  
   172  func (s *syncSuite) TestSyncing(c *gc.C) {
   173  	for i, test := range tests {
   174  		// Perform all tests in a "clean" environment.
   175  		func() {
   176  			s.setUpTest(c)
   177  			defer s.tearDownTest(c)
   178  
   179  			c.Logf("test %d: %s", i, test.description)
   180  
   181  			if test.source {
   182  				test.ctx.Source = s.localStorage
   183  			}
   184  			if test.version != version.Zero {
   185  				version.Current.Number = test.version
   186  			}
   187  			if test.major > 0 {
   188  				test.ctx.MajorVersion = test.major
   189  				test.ctx.MinorVersion = test.minor
   190  			}
   191  			test.ctx.Target = s.targetEnv.Storage()
   192  
   193  			err := sync.SyncTools(test.ctx)
   194  			c.Assert(err, gc.IsNil)
   195  
   196  			targetTools, err := envtools.FindTools(
   197  				s.targetEnv, test.ctx.MajorVersion, test.ctx.MinorVersion, coretools.Filter{}, envtools.DoNotAllowRetry)
   198  			c.Assert(err, gc.IsNil)
   199  			assertToolsList(c, targetTools, test.tools)
   200  			assertNoUnexpectedTools(c, s.targetEnv.Storage())
   201  			assertMirrors(c, s.targetEnv.Storage(), test.expectMirrors)
   202  		}()
   203  	}
   204  }
   205  
   206  var (
   207  	v100p64 = version.MustParseBinary("1.0.0-precise-amd64")
   208  	v100q64 = version.MustParseBinary("1.0.0-quantal-amd64")
   209  	v100q32 = version.MustParseBinary("1.0.0-quantal-i386")
   210  	v100all = []version.Binary{v100p64, v100q64, v100q32}
   211  	v180q64 = version.MustParseBinary("1.8.0-quantal-amd64")
   212  	v180p32 = version.MustParseBinary("1.8.0-precise-i386")
   213  	v180all = []version.Binary{v180q64, v180p32}
   214  	v190q64 = version.MustParseBinary("1.9.0-quantal-amd64")
   215  	v190p32 = version.MustParseBinary("1.9.0-precise-i386")
   216  	v190all = []version.Binary{v190q64, v190p32}
   217  	v1noDev = append(v100all, v180all...)
   218  	v1all   = append(v1noDev, v190all...)
   219  	v200p64 = version.MustParseBinary("2.0.0-precise-amd64")
   220  	v310p64 = version.MustParseBinary("3.1.0-precise-amd64")
   221  	v320p64 = version.MustParseBinary("3.2.0-precise-amd64")
   222  	vAll    = append(append(v1all, v200p64), v310p64, v320p64)
   223  )
   224  
   225  func assertNoUnexpectedTools(c *gc.C, stor storage.StorageReader) {
   226  	// We only expect v1.x tools, no v2.x tools.
   227  	list, err := envtools.ReadList(stor, 2, 0)
   228  	if len(list) > 0 {
   229  		c.Logf("got unexpected tools: %s", list)
   230  	}
   231  	c.Assert(err, gc.Equals, coretools.ErrNoMatches)
   232  }
   233  
   234  func assertToolsList(c *gc.C, list coretools.List, expected []version.Binary) {
   235  	urls := list.URLs()
   236  	c.Check(urls, gc.HasLen, len(expected))
   237  	for _, vers := range expected {
   238  		c.Assert(urls[vers], gc.Not(gc.Equals), "")
   239  	}
   240  }
   241  
   242  func assertMirrors(c *gc.C, stor storage.StorageReader, expectMirrors bool) {
   243  	r, err := storage.Get(stor, "tools/"+simplestreams.UnsignedMirror)
   244  	if err == nil {
   245  		defer r.Close()
   246  	}
   247  	if expectMirrors {
   248  		data, err := ioutil.ReadAll(r)
   249  		c.Assert(err, gc.IsNil)
   250  		c.Assert(string(data), jc.Contains, `"mirrors":`)
   251  	} else {
   252  		c.Assert(err, gc.NotNil)
   253  	}
   254  }
   255  
   256  type uploadSuite struct {
   257  	env environs.Environ
   258  	coretesting.FakeJujuHomeSuite
   259  	envtesting.ToolsFixture
   260  }
   261  
   262  func (s *uploadSuite) SetUpTest(c *gc.C) {
   263  	s.FakeJujuHomeSuite.SetUpTest(c)
   264  	s.ToolsFixture.SetUpTest(c)
   265  	// We only want to use simplestreams to find any synced tools.
   266  	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig())
   267  	c.Assert(err, gc.IsNil)
   268  	s.env, err = environs.Prepare(cfg, coretesting.Context(c), configstore.NewMem())
   269  	c.Assert(err, gc.IsNil)
   270  }
   271  
   272  func (s *uploadSuite) TearDownTest(c *gc.C) {
   273  	dummy.Reset()
   274  	s.ToolsFixture.TearDownTest(c)
   275  	s.FakeJujuHomeSuite.TearDownTest(c)
   276  }
   277  
   278  func (s *uploadSuite) TestUpload(c *gc.C) {
   279  	t, err := sync.Upload(s.env.Storage(), nil)
   280  	c.Assert(err, gc.IsNil)
   281  	c.Assert(t.Version, gc.Equals, version.Current)
   282  	c.Assert(t.URL, gc.Not(gc.Equals), "")
   283  	// TODO(waigani) Does this test need to download tools? If not,
   284  	// sync.bundleTools can be mocked to improve test speed.
   285  	dir := downloadTools(c, t)
   286  	out, err := exec.Command(filepath.Join(dir, "jujud"), "version").CombinedOutput()
   287  	c.Assert(err, gc.IsNil)
   288  	c.Assert(string(out), gc.Equals, version.Current.String()+"\n")
   289  }
   290  
   291  func (s *uploadSuite) TestUploadFakeSeries(c *gc.C) {
   292  	seriesToUpload := "precise"
   293  	if seriesToUpload == version.Current.Series {
   294  		seriesToUpload = "raring"
   295  	}
   296  	t, err := sync.Upload(s.env.Storage(), nil, "quantal", seriesToUpload)
   297  	c.Assert(err, gc.IsNil)
   298  	s.assertUploadedTools(c, t, seriesToUpload)
   299  }
   300  
   301  func (s *uploadSuite) TestUploadAndForceVersion(c *gc.C) {
   302  	// This test actually tests three things:
   303  	//   the writing of the FORCE-VERSION file;
   304  	//   the reading of the FORCE-VERSION file by the version package;
   305  	//   and the reading of the version from jujud.
   306  	vers := version.Current
   307  	vers.Patch++
   308  	t, err := sync.Upload(s.env.Storage(), &vers.Number)
   309  	c.Assert(err, gc.IsNil)
   310  	c.Assert(t.Version, gc.Equals, vers)
   311  }
   312  
   313  func (s *uploadSuite) TestSyncTools(c *gc.C) {
   314  	s.PatchValue(&envtools.BundleTools, toolstesting.GetMockBundleTools(c))
   315  	builtTools, err := sync.BuildToolsTarball(nil)
   316  	c.Assert(err, gc.IsNil)
   317  	t, err := sync.SyncBuiltTools(s.env.Storage(), builtTools)
   318  	c.Assert(err, gc.IsNil)
   319  	c.Assert(t.Version, gc.Equals, version.Current)
   320  	c.Assert(t.URL, gc.Not(gc.Equals), "")
   321  }
   322  
   323  func (s *uploadSuite) TestSyncToolsFakeSeries(c *gc.C) {
   324  	seriesToUpload := "precise"
   325  	if seriesToUpload == version.Current.Series {
   326  		seriesToUpload = "raring"
   327  	}
   328  	builtTools, err := sync.BuildToolsTarball(nil)
   329  	c.Assert(err, gc.IsNil)
   330  
   331  	t, err := sync.SyncBuiltTools(s.env.Storage(), builtTools, "quantal", seriesToUpload)
   332  	c.Assert(err, gc.IsNil)
   333  	s.assertUploadedTools(c, t, seriesToUpload)
   334  }
   335  
   336  func (s *uploadSuite) TestSyncAndForceVersion(c *gc.C) {
   337  	// This test actually tests three things:
   338  	//   the writing of the FORCE-VERSION file;
   339  	//   the reading of the FORCE-VERSION file by the version package;
   340  	//   and the reading of the version from jujud.
   341  	vers := version.Current
   342  	vers.Patch++
   343  	builtTools, err := sync.BuildToolsTarball(&vers.Number)
   344  	c.Assert(err, gc.IsNil)
   345  	t, err := sync.SyncBuiltTools(s.env.Storage(), builtTools)
   346  	c.Assert(err, gc.IsNil)
   347  	c.Assert(t.Version, gc.Equals, vers)
   348  }
   349  
   350  func (s *uploadSuite) assertUploadedTools(c *gc.C, t *coretools.Tools, uploadedSeries string) {
   351  	c.Assert(t.Version, gc.Equals, version.Current)
   352  	expectRaw := downloadToolsRaw(c, t)
   353  
   354  	list, err := envtools.ReadList(s.env.Storage(), version.Current.Major, version.Current.Minor)
   355  	c.Assert(err, gc.IsNil)
   356  	c.Assert(list, gc.HasLen, 3)
   357  	expectSeries := []string{"quantal", uploadedSeries, version.Current.Series}
   358  	sort.Strings(expectSeries)
   359  	c.Assert(list.AllSeries(), gc.DeepEquals, expectSeries)
   360  	for _, t := range list {
   361  		c.Logf("checking %s", t.URL)
   362  		c.Assert(t.Version.Number, gc.Equals, version.Current.Number)
   363  		actualRaw := downloadToolsRaw(c, t)
   364  		c.Assert(string(actualRaw), gc.Equals, string(expectRaw))
   365  	}
   366  	metadata := toolstesting.ParseMetadataFromStorage(c, s.env.Storage(), false)
   367  	c.Assert(metadata, gc.HasLen, 3)
   368  	for i, tm := range metadata {
   369  		c.Assert(tm.Release, gc.Equals, expectSeries[i])
   370  		c.Assert(tm.Version, gc.Equals, version.Current.Number.String())
   371  	}
   372  }
   373  
   374  // downloadTools downloads the supplied tools and extracts them into a
   375  // new directory.
   376  func downloadTools(c *gc.C, t *coretools.Tools) string {
   377  	resp, err := utils.GetValidatingHTTPClient().Get(t.URL)
   378  	c.Assert(err, gc.IsNil)
   379  	defer resp.Body.Close()
   380  	cmd := exec.Command("tar", "xz")
   381  	cmd.Dir = c.MkDir()
   382  	cmd.Stdin = resp.Body
   383  	out, err := cmd.CombinedOutput()
   384  	c.Assert(err, gc.IsNil, gc.Commentf(string(out)))
   385  	return cmd.Dir
   386  }
   387  
   388  // downloadToolsRaw downloads the supplied tools and returns the raw bytes.
   389  func downloadToolsRaw(c *gc.C, t *coretools.Tools) []byte {
   390  	resp, err := utils.GetValidatingHTTPClient().Get(t.URL)
   391  	c.Assert(err, gc.IsNil)
   392  	defer resp.Body.Close()
   393  	c.Assert(resp.StatusCode, gc.Equals, http.StatusOK)
   394  	var buf bytes.Buffer
   395  	_, err = io.Copy(&buf, resp.Body)
   396  	c.Assert(err, gc.IsNil)
   397  	return buf.Bytes()
   398  }
   399  
   400  func bundleTools(c *gc.C) (version.Binary, string, error) {
   401  	f, err := ioutil.TempFile("", "juju-tgz")
   402  	c.Assert(err, gc.IsNil)
   403  	defer f.Close()
   404  	defer os.Remove(f.Name())
   405  
   406  	return envtools.BundleTools(f, &version.Current.Number)
   407  }
   408  
   409  type badBuildSuite struct {
   410  	env environs.Environ
   411  	gitjujutesting.LoggingSuite
   412  	gitjujutesting.CleanupSuite
   413  	envtesting.ToolsFixture
   414  }
   415  
   416  var badGo = `
   417  #!/bin/bash --norc
   418  exit 1
   419  `[1:]
   420  
   421  func (s *badBuildSuite) SetUpSuite(c *gc.C) {
   422  	s.CleanupSuite.SetUpSuite(c)
   423  	s.LoggingSuite.SetUpSuite(c)
   424  }
   425  
   426  func (s *badBuildSuite) TearDownSuite(c *gc.C) {
   427  	s.LoggingSuite.TearDownSuite(c)
   428  	s.CleanupSuite.TearDownSuite(c)
   429  }
   430  
   431  func (s *badBuildSuite) SetUpTest(c *gc.C) {
   432  	s.CleanupSuite.SetUpTest(c)
   433  	s.LoggingSuite.SetUpTest(c)
   434  	s.ToolsFixture.SetUpTest(c)
   435  	// We only want to use simplestreams to find any synced tools.
   436  	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig())
   437  	c.Assert(err, gc.IsNil)
   438  	s.env, err = environs.Prepare(cfg, coretesting.Context(c), configstore.NewMem())
   439  	c.Assert(err, gc.IsNil)
   440  
   441  	// Mock go cmd
   442  	testPath := c.MkDir()
   443  	s.PatchEnvPathPrepend(testPath)
   444  	path := filepath.Join(testPath, "go")
   445  	err = ioutil.WriteFile(path, []byte(badGo), 0755)
   446  	c.Assert(err, gc.IsNil)
   447  
   448  	// Check mocked go cmd errors
   449  	out, err := exec.Command("go").CombinedOutput()
   450  	c.Assert(err, gc.ErrorMatches, "exit status 1")
   451  	c.Assert(string(out), gc.Equals, "")
   452  }
   453  
   454  func (s *badBuildSuite) TearDownTest(c *gc.C) {
   455  	dummy.Reset()
   456  	s.ToolsFixture.TearDownTest(c)
   457  	s.LoggingSuite.TearDownTest(c)
   458  	s.CleanupSuite.TearDownTest(c)
   459  }
   460  
   461  func (s *badBuildSuite) TestBundleToolsBadBuild(c *gc.C) {
   462  	// Test that original bundleTools Func fails as expected
   463  	vers, sha256Hash, err := bundleTools(c)
   464  	c.Assert(vers, gc.DeepEquals, version.Binary{})
   465  	c.Assert(sha256Hash, gc.Equals, "")
   466  	c.Assert(err, gc.ErrorMatches, `build command "go" failed: exit status 1; `)
   467  
   468  	s.PatchValue(&envtools.BundleTools, toolstesting.GetMockBundleTools(c))
   469  
   470  	// Test that BundleTools func passes after it is
   471  	// mocked out
   472  	vers, sha256Hash, err = bundleTools(c)
   473  	c.Assert(err, gc.IsNil)
   474  	c.Assert(vers.Number, gc.Equals, version.Current.Number)
   475  	c.Assert(sha256Hash, gc.Equals, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
   476  }
   477  
   478  func (s *badBuildSuite) TestUploadToolsBadBuild(c *gc.C) {
   479  	// Test that original Upload Func fails as expected
   480  	t, err := sync.Upload(s.env.Storage(), nil)
   481  	c.Assert(t, gc.IsNil)
   482  	c.Assert(err, gc.ErrorMatches, `build command "go" failed: exit status 1; `)
   483  
   484  	// Test that Upload func passes after BundleTools func is mocked out
   485  	s.PatchValue(&envtools.BundleTools, toolstesting.GetMockBundleTools(c))
   486  	t, err = sync.Upload(s.env.Storage(), nil)
   487  	c.Assert(err, gc.IsNil)
   488  	c.Assert(t.Version, gc.Equals, version.Current)
   489  	c.Assert(t.URL, gc.Not(gc.Equals), "")
   490  }
   491  
   492  func (s *badBuildSuite) TestBuildToolsBadBuild(c *gc.C) {
   493  	// Test that original BuildToolsTarball fails
   494  	builtTools, err := sync.BuildToolsTarball(nil)
   495  	c.Assert(err, gc.ErrorMatches, `build command "go" failed: exit status 1; `)
   496  	c.Assert(builtTools, gc.IsNil)
   497  
   498  	// Test that BuildToolsTarball func passes after BundleTools func is
   499  	// mocked out
   500  	s.PatchValue(&envtools.BundleTools, toolstesting.GetMockBundleTools(c))
   501  	builtTools, err = sync.BuildToolsTarball(nil)
   502  	c.Assert(builtTools.Version, gc.Equals, version.Current)
   503  	c.Assert(err, gc.IsNil)
   504  }
   505  
   506  func (s *uploadSuite) TestMockBundleTools(c *gc.C) {
   507  	var (
   508  		writer       io.Writer
   509  		forceVersion *version.Number
   510  		n            int
   511  		p            bytes.Buffer
   512  	)
   513  	p.WriteString("Hello World")
   514  
   515  	s.PatchValue(&envtools.BundleTools, func(writerArg io.Writer, forceVersionArg *version.Number) (vers version.Binary, sha256Hash string, err error) {
   516  		writer = writerArg
   517  		n, err = writer.Write(p.Bytes())
   518  		c.Assert(err, gc.IsNil)
   519  		forceVersion = forceVersionArg
   520  		return
   521  	})
   522  
   523  	_, err := sync.BuildToolsTarball(&version.Current.Number)
   524  	c.Assert(err, gc.IsNil)
   525  	c.Assert(*forceVersion, gc.Equals, version.Current.Number)
   526  	c.Assert(writer, gc.NotNil)
   527  	c.Assert(n, gc.Equals, len(p.Bytes()))
   528  }
   529  
   530  func (s *uploadSuite) TestMockBuildTools(c *gc.C) {
   531  	s.PatchValue(&version.Current, version.MustParseBinary("1.9.1-trusty-amd64"))
   532  	buildToolsFunc := toolstesting.GetMockBuildTools(c)
   533  	builtTools, err := buildToolsFunc(nil)
   534  	c.Assert(err, gc.IsNil)
   535  
   536  	builtTools.Dir = ""
   537  
   538  	expectedBuiltTools := &sync.BuiltTools{
   539  		StorageName: "name",
   540  		Version:     version.Current,
   541  		Size:        127,
   542  		Sha256Hash:  "6a19d08ca4913382ca86508aa38eb8ee5b9ae2d74333fe8d862c0f9e29b82c39",
   543  	}
   544  	c.Assert(builtTools, gc.DeepEquals, expectedBuiltTools)
   545  
   546  	vers := version.MustParseBinary("1.5.3-trusty-amd64")
   547  	builtTools, err = buildToolsFunc(&vers.Number)
   548  	c.Assert(err, gc.IsNil)
   549  	builtTools.Dir = ""
   550  	expectedBuiltTools = &sync.BuiltTools{
   551  		StorageName: "name",
   552  		Version:     vers,
   553  		Size:        127,
   554  		Sha256Hash:  "cad8ccedab8f26807ff379ddc2f2f78d9a7cac1276e001154cee5e39b9ddcc38",
   555  	}
   556  	c.Assert(builtTools, gc.DeepEquals, expectedBuiltTools)
   557  }