@VisibleForTesting
  static Optional<LocalImage> getCachedDockerImage(Cache cache, ImageDetails dockerImageDetails)
      throws DigestException, IOException, CacheCorruptedException {
    // Get config
    Optional<ContainerConfigurationTemplate> cachedConfig =
        cache.retrieveLocalConfig(dockerImageDetails.getImageId());
    if (!cachedConfig.isPresent()) {
      return Optional.empty();
    }

    // Get layers
    List<Future<PreparedLayer>> cachedLayers = new ArrayList<>();
    for (DescriptorDigest diffId : dockerImageDetails.getDiffIds()) {
      Optional<CachedLayer> cachedLayer = cache.retrieveTarLayer(diffId);
      if (!cachedLayer.isPresent()) {
        return Optional.empty();
      }
      CachedLayer layer = cachedLayer.get();
      cachedLayers.add(Futures.immediateFuture(new PreparedLayer.Builder(layer).build()));
    }

    return Optional.of(new LocalImage(cachedLayers, cachedConfig.get()));
  }
@Test
  public void testGetCachedDockerImage()
      throws IOException, DigestException, CacheDirectoryCreationException, CacheCorruptedException,
          URISyntaxException {
    String dockerInspectJson =
        "{\"Size\": 0,"
            + "\"Id\": \"sha256:066872f17ae819f846a6d5abcfc3165abe13fb0a157640fa8cb7af81077670c0\","
            + "\"RootFS\": { \"Layers\": ["
            + "  \"sha256:5e701122d3347fae0758cd5b7f0692c686fcd07b0e7fd9c4a125fbdbbedc04dd\","
            + "  \"sha256:f1ac3015bcbf0ada4750d728626eb10f0f585199e2b667dcd79e49f0e926178e\" ] } }";
    ImageDetails dockerImageDetails =
        JsonTemplateMapper.readJson(dockerInspectJson, CliDockerClient.DockerImageDetails.class);
    Path cachePath = temporaryFolder.newFolder("cache").toPath();
    Files.createDirectories(cachePath.resolve("local/config"));
    Cache cache = Cache.withDirectory(cachePath);

    // Image not in cache
    Optional<LocalImage> localImage =
        LocalBaseImageSteps.getCachedDockerImage(cache, dockerImageDetails);
    Assert.assertFalse(localImage.isPresent());

    // Config in cache, but not layers
    String configHash = "066872f17ae819f846a6d5abcfc3165abe13fb0a157640fa8cb7af81077670c0";
    Files.copy(
        getResource("core/extraction/test-cache/local/config/" + configHash),
        cachePath.resolve("local/config/" + configHash));
    localImage = LocalBaseImageSteps.getCachedDockerImage(cache, dockerImageDetails);
    Assert.assertFalse(localImage.isPresent());

    // One layer missing
    String diffId = "5e701122d3347fae0758cd5b7f0692c686fcd07b0e7fd9c4a125fbdbbedc04dd";
    String digest = "0011328ac5dfe3dde40c7c5e0e00c98d1833a3aeae2bfb668cf9eb965c229c7f";
    Files.createDirectories(cachePath.resolve("local").resolve(diffId));
    Files.copy(
        getResource("core/extraction/test-cache/local/" + diffId + "/" + digest),
        cachePath.resolve("local").resolve(diffId).resolve(digest));
    localImage = LocalBaseImageSteps.getCachedDockerImage(cache, dockerImageDetails);
    Assert.assertFalse(localImage.isPresent());

    // Image fully in cache
    diffId = "f1ac3015bcbf0ada4750d728626eb10f0f585199e2b667dcd79e49f0e926178e";
    digest = "c10ef24a5cef5092bbcb5a5666721cff7b86ce978c203a958d1fc86ee6c19f94";
    Files.createDirectories(cachePath.resolve("local").resolve(diffId));
    Files.copy(
        getResource("core/extraction/test-cache/local/" + diffId + "/" + digest),
        cachePath.resolve("local").resolve(diffId).resolve(digest));
    localImage = LocalBaseImageSteps.getCachedDockerImage(cache, dockerImageDetails);
    Assert.assertTrue(localImage.isPresent());
    LocalImage image = localImage.get();
    Assert.assertEquals(2, image.configurationTemplate.getLayerCount());
    Assert.assertEquals(2, image.layers.size());
  }