logger             boshlog.Logger
		retryableBlobstore boshblob.Blobstore
	)

	BeforeEach(func() {
		innerBlobstore = &fakeblob.FakeBlobstore{}
		logger = boshlog.NewLogger(boshlog.LevelNone)
		retryableBlobstore = boshblob.NewRetryableBlobstore(innerBlobstore, 3, logger)
	})

	Describe("Get", func() {
		Context("when inner blobstore succeeds before maximum number of get tries (first time)", func() {
			It("returns path without an error", func() {
				innerBlobstore.GetFileName = "fake-path"

				path, err := retryableBlobstore.Get("fake-blob-id", "fake-fingerprint")
				Expect(err).ToNot(HaveOccurred())
				Expect(path).To(Equal("fake-path"))

				Expect(innerBlobstore.GetBlobIDs).To(Equal([]string{"fake-blob-id"}))
				Expect(innerBlobstore.GetFingerprints).To(Equal([]string{"fake-fingerprint"}))
			})
		})

		Context("when inner blobstore succeed exactly at maximum number of get tries", func() {
			It("returns path without an error", func() {
				innerBlobstore.GetFileNames = []string{"", "", "fake-last-path"}
				innerBlobstore.GetErrs = []error{
					errors.New("fake-get-err-1"),
					errors.New("fake-get-err-2"),
					nil,
	var (
		innerBlobstore          *fakeblob.FakeBlobstore
		sha1VerifiableBlobstore boshblob.Blobstore
	)

	BeforeEach(func() {
		innerBlobstore = &fakeblob.FakeBlobstore{}
		sha1VerifiableBlobstore = boshblob.NewSHA1VerifiableBlobstore(innerBlobstore)
	})

	Describe("Get", func() {
		It("returns without an error if sha1 matches", func() {
			innerBlobstore.GetFileName = fixturePath

			fileName, err := sha1VerifiableBlobstore.Get("fake-blob-id", fixtureSHA1)
			Expect(err).ToNot(HaveOccurred())

			Expect(innerBlobstore.GetBlobIDs).To(Equal([]string{"fake-blob-id"}))
			Expect(fileName).To(Equal(fixturePath))
		})

		It("returns error if sha1 does not match", func() {
			innerBlobstore.GetFileName = fixturePath
			incorrectSha1 := "some-incorrect-sha1"

			_, err := sha1VerifiableBlobstore.Get("fake-blob-id", incorrectSha1)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("SHA1 mismatch"))
		})
	)

	BeforeEach(func() {
		innerBlobstore = &fakeblob.FakeBlobstore{}
		blobManager = &fakeblob.FakeBlobManagerInterface{}
		logger := boshlog.NewLogger(boshlog.LevelNone)

		cascadingBlobstore = blobstore.NewCascadingBlobstore(innerBlobstore, blobManager, logger)
	})

	Describe("Get", func() {
		Describe("when blobManager returns the file path", func() {
			It("returns the path provided by the blobManager", func() {
				blobManager.GetPathReturns("/path/to-copy/of-blob", nil)

				filename, err := cascadingBlobstore.Get("blobID", boshcrypto.NewDigest("sha1", "fake-checksum"))

				Expect(err).To(BeNil())
				Expect(filename).To(Equal("/path/to-copy/of-blob"))

				Expect(blobManager.GetPathCallCount()).To(Equal(1))
				Expect(blobManager.GetPathArgsForCall(0)).To(Equal("blobID"))

				Expect(innerBlobstore.GetBlobIDs).Should(BeEmpty())
			})
		})

		Describe("when blobManager returns an error", func() {
			It("delegates the action of getting the blob to inner blobstore", func() {
				blobID := "smurf-4"
				digest := boshcrypto.NewDigest("sha1", "smurf-4-sha")
		logger             boshlog.Logger
		retryableBlobstore boshblob.Blobstore
	)

	BeforeEach(func() {
		innerBlobstore = &fakeblob.FakeBlobstore{}
		logger = boshlog.NewLogger(boshlog.LevelNone)
		retryableBlobstore = boshblob.NewRetryableBlobstore(innerBlobstore, 3, logger)
	})

	Describe("Get", func() {
		Context("when inner blobstore succeeds before maximum number of get tries (first time)", func() {
			It("returns path without an error", func() {
				innerBlobstore.GetFileName = "fake-path"

				path, err := retryableBlobstore.Get("fake-blob-id", boshcrypto.NewDigest("fake", "fingerprint"))
				Expect(err).ToNot(HaveOccurred())
				Expect(path).To(Equal("fake-path"))

				Expect(innerBlobstore.GetBlobIDs).To(Equal([]string{"fake-blob-id"}))
				Expect(innerBlobstore.GetFingerprints).To(Equal([]boshcrypto.Digest{boshcrypto.NewDigest("fake", "fingerprint")}))
			})
		})

		Context("when inner blobstore succeed exactly at maximum number of get tries", func() {
			It("returns path without an error", func() {
				innerBlobstore.GetFileNames = []string{"", "", "fake-last-path"}
				innerBlobstore.GetErrs = []error{
					errors.New("fake-get-err-1"),
					errors.New("fake-get-err-2"),
					nil,
		checksumProvider            boshcrypto.DigestProvider
		fixtureDigest               boshcrypto.Digest
	)

	BeforeEach(func() {
		fixtureDigest = boshcrypto.NewDigest(boshcrypto.DigestAlgorithmSHA1, fixtureSHA1)
		innerBlobstore = &fakeblob.FakeBlobstore{}
		checksumProvider = boshcrypto.NewDigestProvider(fakesys.NewFakeFileSystem())
		checksumVerifiableBlobstore = boshblob.NewDigestVerifiableBlobstore(innerBlobstore, checksumProvider)
	})

	Describe("Get", func() {
		It("returns without an error if sha1 matches", func() {
			innerBlobstore.GetFileName = fixturePath

			fileName, err := checksumVerifiableBlobstore.Get("fake-blob-id", fixtureDigest)
			Expect(err).ToNot(HaveOccurred())

			Expect(innerBlobstore.GetBlobIDs).To(Equal([]string{"fake-blob-id"}))
			Expect(fileName).To(Equal(fixturePath))
		})

		It("returns error if sha1 does not match", func() {
			innerBlobstore.GetFileName = fixturePath
			incorrectSha1 := boshcrypto.NewDigest(boshcrypto.DigestAlgorithmSHA1, "some-incorrect-sha1")

			_, err := checksumVerifiableBlobstore.Get("fake-blob-id", incorrectSha1)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("Expected sha1 digest"))
		})