@Before
  public void setup() throws IOException {
    artifact = new DefaultArtifact("gid", "aid", "jar", "ver");
    artifact = artifact.setFile(TestFileUtils.createTempFile("artifact".getBytes(), 1));
    metadata =
        new DefaultMetadata(
            "gid",
            "aid",
            "ver",
            "type",
            Nature.RELEASE_OR_SNAPSHOT,
            TestFileUtils.createTempFile("metadata".getBytes(), 1));

    session = TestUtils.newSession();
    localArtifactPath = session.getLocalRepositoryManager().getPathForLocalArtifact(artifact);
    localMetadataPath = session.getLocalRepositoryManager().getPathForLocalMetadata(metadata);

    localArtifactFile = new File(session.getLocalRepository().getBasedir(), localArtifactPath);

    installer = new DefaultInstaller();
    installer.setFileProcessor(new TestFileProcessor());
    installer.setRepositoryEventDispatcher(new StubRepositoryEventDispatcher());
    installer.setSyncContextFactory(new StubSyncContextFactory());
    request = new InstallRequest();
    listener = new RecordingRepositoryListener();
    session.setRepositoryListener(listener);

    lrm = (TestLocalRepositoryManager) session.getLocalRepositoryManager();

    TestFileUtils.deleteFile(session.getLocalRepository().getBasedir());
  }
  @Test
  public void testReadNoFileLeak() throws Exception {
    TrackingFileManager tfm = new TrackingFileManager();

    for (int i = 0; i < 1000; i++) {
      File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");
      assertNotNull(tfm.read(propFile));
      assertTrue("Leaked file: " + propFile, propFile.delete());
    }
  }
  @Test
  public void testUpdateNoFileLeak() throws Exception {
    TrackingFileManager tfm = new TrackingFileManager();

    Map<String, String> updates = new HashMap<String, String>();
    updates.put("k", "v");

    for (int i = 0; i < 1000; i++) {
      File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");
      assertNotNull(tfm.update(propFile, updates));
      assertTrue("Leaked file: " + propFile, propFile.delete());
    }
  }
  @Test
  public void testRead() throws Exception {
    TrackingFileManager tfm = new TrackingFileManager();

    File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");
    Properties props = tfm.read(propFile);

    assertNotNull(props);
    assertEquals(String.valueOf(props), 2, props.size());
    assertEquals("value1", props.get("key1"));
    assertEquals("value2", props.get("key2"));

    assertTrue("Leaked file: " + propFile, propFile.delete());

    props = tfm.read(propFile);
    assertNull(String.valueOf(props), props);
  }
  @Test
  public void testLockingOnCanonicalPath() throws Exception {
    final TrackingFileManager tfm = new TrackingFileManager();

    final File propFile = TestFileUtils.createTempFile("#COMMENT\nkey1=value1\nkey2 : value2");

    final List<Throwable> errors = Collections.synchronizedList(new ArrayList<Throwable>());

    Thread[] threads = new Thread[4];
    for (int i = 0; i < threads.length; i++) {
      String path = propFile.getParent();
      for (int j = 0; j < i; j++) {
        path += "/.";
      }
      path += "/" + propFile.getName();
      final File file = new File(path);

      threads[i] =
          new Thread() {
            public void run() {
              try {
                for (int i = 0; i < 1000; i++) {
                  assertNotNull(tfm.read(file));
                }
              } catch (Throwable e) {
                errors.add(e);
              }
            }
          };
    }

    for (int i = 0; i < threads.length; i++) {
      threads[i].start();
    }

    for (int i = 0; i < threads.length; i++) {
      threads[i].join();
    }

    assertEquals(Collections.emptyList(), errors);
  }
  @Test
  public void testUpdate() throws Exception {
    TrackingFileManager tfm = new TrackingFileManager();

    // NOTE: The excessive repetitions are to check the update properly truncates the file
    File propFile =
        TestFileUtils.createTempFile("key1=value1\nkey2 : value2\n".getBytes("UTF-8"), 1000);

    Map<String, String> updates = new HashMap<String, String>();
    updates.put("key1", "v");
    updates.put("key2", null);

    tfm.update(propFile, updates);

    Properties props = tfm.read(propFile);

    assertNotNull(props);
    assertEquals(String.valueOf(props), 1, props.size());
    assertEquals("v", props.get("key1"));
    assertNull(String.valueOf(props.get("key2")), props.get("key2"));
  }