@Test
public void testMain() throws Exception {

  ContainerLocalizerWrapper wrapper = new ContainerLocalizerWrapper();
  ContainerLocalizer localizer =
      wrapper.setupContainerLocalizerForTest();
  Random random = wrapper.random;
  List<Path> localDirs = wrapper.localDirs;
  Path tokenPath = wrapper.tokenPath;
  LocalizationProtocol nmProxy = wrapper.nmProxy;
  AbstractFileSystem spylfs = wrapper.spylfs;
  mockOutDownloads(localizer);
  // verify created cache
  List<Path> privCacheList = new ArrayList<Path>();
  List<Path> appCacheList = new ArrayList<Path>();
  for (Path p : localDirs) {
    Path base = new Path(new Path(p, ContainerLocalizer.USERCACHE), appUser);
    Path privcache = new Path(base, ContainerLocalizer.FILECACHE);
    privCacheList.add(privcache);
    Path appDir =
        new Path(base, new Path(ContainerLocalizer.APPCACHE, appId));
    Path appcache = new Path(appDir, ContainerLocalizer.FILECACHE);
    appCacheList.add(appcache);
  }
  // mock heartbeat responses from NM
  ResourceLocalizationSpec rsrcA =
      getMockRsrc(random, LocalResourceVisibility.PRIVATE,
        privCacheList.get(0));
  ResourceLocalizationSpec rsrcB =
      getMockRsrc(random, LocalResourceVisibility.PRIVATE,
        privCacheList.get(0));
  ResourceLocalizationSpec rsrcC =
      getMockRsrc(random, LocalResourceVisibility.APPLICATION,
        appCacheList.get(0));
  ResourceLocalizationSpec rsrcD =
      getMockRsrc(random, LocalResourceVisibility.PRIVATE,
        privCacheList.get(0));
  when(nmProxy.heartbeat(isA(LocalizerStatus.class)))
    .thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
          Collections.singletonList(rsrcA)))
    .thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
          Collections.singletonList(rsrcB)))
    .thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
          Collections.singletonList(rsrcC)))
    .thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
          Collections.singletonList(rsrcD)))
    .thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.LIVE,
          Collections.<ResourceLocalizationSpec>emptyList()))
    .thenReturn(new MockLocalizerHeartbeatResponse(LocalizerAction.DIE,
          null));
  LocalResource tRsrcA = rsrcA.getResource();
  LocalResource tRsrcB = rsrcB.getResource();
  LocalResource tRsrcC = rsrcC.getResource();
  LocalResource tRsrcD = rsrcD.getResource();
  doReturn(
    new FakeDownload(rsrcA.getResource().getResource().getFile(), true))
    .when(localizer).download(isA(Path.class), eq(tRsrcA),
      isA(UserGroupInformation.class));
  doReturn(
    new FakeDownload(rsrcB.getResource().getResource().getFile(), true))
    .when(localizer).download(isA(Path.class), eq(tRsrcB),
      isA(UserGroupInformation.class));
  doReturn(
    new FakeDownload(rsrcC.getResource().getResource().getFile(), true))
    .when(localizer).download(isA(Path.class), eq(tRsrcC),
      isA(UserGroupInformation.class));
  doReturn(
    new FakeDownload(rsrcD.getResource().getResource().getFile(), true))
    .when(localizer).download(isA(Path.class), eq(tRsrcD),
      isA(UserGroupInformation.class));
  // run localization
  localizer.runLocalization(nmAddr);
  for (Path p : localDirs) {
    Path base = new Path(new Path(p, ContainerLocalizer.USERCACHE), appUser);
    Path privcache = new Path(base, ContainerLocalizer.FILECACHE);
    // $x/usercache/$user/filecache
    verify(spylfs).mkdir(eq(privcache), eq(CACHE_DIR_PERM), eq(false));
    Path appDir =
      new Path(base, new Path(ContainerLocalizer.APPCACHE, appId));
    // $x/usercache/$user/appcache/$appId/filecache
    Path appcache = new Path(appDir, ContainerLocalizer.FILECACHE);
    verify(spylfs).mkdir(eq(appcache), eq(CACHE_DIR_PERM), eq(false));
  }
  // verify tokens read at expected location
  verify(spylfs).open(tokenPath);
  // verify downloaded resources reported to NM
  verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcA.getResource())));
  verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcB.getResource())));
  verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcC.getResource())));
  verify(nmProxy).heartbeat(argThat(new HBMatches(rsrcD.getResource())));
  // verify all HB use localizerID provided
  verify(nmProxy, never()).heartbeat(argThat(
      status -> !containerId.equals(status.getLocalizerId())));
}