@VisibleForTesting
  Optional<ImagesAndRegistryClient> tryMirrors(
      BuildContext buildContext, ProgressEventDispatcher.Factory progressDispatcherFactory)
      throws LayerCountMismatchException, BadContainerConfigurationFormatException {
    EventHandlers eventHandlers = buildContext.getEventHandlers();

    Collection<Map.Entry<String, String>> mirrorEntries =
        buildContext.getRegistryMirrors().entries();
    try (ProgressEventDispatcher progressDispatcher1 =
            progressDispatcherFactory.create("trying mirrors", mirrorEntries.size());
        TimerEventDispatcher ignored1 = new TimerEventDispatcher(eventHandlers, "trying mirrors")) {
      for (Map.Entry<String, String> entry : mirrorEntries) {
        String registry = entry.getKey();
        String mirror = entry.getValue();
        eventHandlers.dispatch(LogEvent.debug("mirror config: " + registry + " --> " + mirror));

        if (!buildContext.getBaseImageConfiguration().getImageRegistry().equals(registry)) {
          progressDispatcher1.dispatchProgress(1);
          continue;
        }

        eventHandlers.dispatch(LogEvent.info("trying mirror " + mirror + " for the base image"));
        try (ProgressEventDispatcher progressDispatcher2 =
            progressDispatcher1.newChildProducer().create("trying mirror " + mirror, 2)) {
          RegistryClient registryClient =
              buildContext.newBaseImageRegistryClientFactory(mirror).newRegistryClient();
          List<Image> images = pullPublicImages(registryClient, progressDispatcher2);
          eventHandlers.dispatch(LogEvent.info("pulled manifest from mirror " + mirror));
          return Optional.of(new ImagesAndRegistryClient(images, registryClient));

        } catch (IOException | RegistryException ex) {
          // Ignore errors from this mirror and continue.
          eventHandlers.dispatch(
              LogEvent.debug(
                  "failed to get manifest from mirror " + mirror + ": " + ex.getMessage()));
        }
      }
      return Optional.empty();
    }
  }
@Test
  public void testTryMirrors_multipleMirrors()
      throws LayerCountMismatchException, BadContainerConfigurationFormatException, IOException,
          RegistryException, InvalidImageReferenceException {
    Mockito.when(imageConfiguration.getImage()).thenReturn(ImageReference.parse("registry/repo"));
    Mockito.when(imageConfiguration.getImageRegistry()).thenReturn("registry");
    Mockito.when(buildContext.getRegistryMirrors())
        .thenReturn(ImmutableListMultimap.of("registry", "quay.io", "registry", "gcr.io"));

    Mockito.when(buildContext.newBaseImageRegistryClientFactory("quay.io"))
        .thenReturn(registryClientFactory);
    Mockito.when(registryClient.pullManifest(Mockito.any()))
        .thenThrow(new RegistryException("not found"));
    Mockito.when(containerConfig.getPlatforms())
        .thenReturn(ImmutableSet.of(new Platform("amd64", "linux")));

    RegistryClient.Factory gcrRegistryClientFactory =
        setUpWorkingRegistryClientFactoryWithV22ManifestTemplate();
    Mockito.when(buildContext.newBaseImageRegistryClientFactory("gcr.io"))
        .thenReturn(gcrRegistryClientFactory);

    Optional<ImagesAndRegistryClient> result =
        pullBaseImageStep.tryMirrors(buildContext, progressDispatcherFactory);
    Assert.assertTrue(result.isPresent());
    Assert.assertEquals(gcrRegistryClientFactory.newRegistryClient(), result.get().registryClient);

    InOrder inOrder = Mockito.inOrder(eventHandlers);
    inOrder
        .verify(eventHandlers)
        .dispatch(LogEvent.info("trying mirror quay.io for the base image"));
    inOrder
        .verify(eventHandlers)
        .dispatch(LogEvent.debug("failed to get manifest from mirror quay.io: not found"));
    inOrder
        .verify(eventHandlers)
        .dispatch(LogEvent.info("trying mirror gcr.io for the base image"));
    inOrder.verify(eventHandlers).dispatch(LogEvent.info("pulled manifest from mirror gcr.io"));
  }