// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.config;

import junit.framework.TestCase;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.UUID;

public class SitePathsTest extends TestCase {
  public void testCreate_NotExisting() throws FileNotFoundException {
    final File root = random();
    final SitePaths site = new SitePaths(root);
    assertTrue(site.isNew);
    assertEquals(root, site.site_path);
    assertEquals(new File(root, "etc"), site.etc_dir);
  }

  public void testCreate_Empty() throws FileNotFoundException {
    final File root = random();
    try {
      assertTrue(root.mkdir());

      final SitePaths site = new SitePaths(root);
      assertTrue(site.isNew);
      assertEquals(root, site.site_path);
    } finally {
      root.delete();
    }
  }

  public void testCreate_NonEmpty() throws IOException {
    final File root = random();
    final File txt = new File(root, "test.txt");
    try {
      assertTrue(root.mkdir());
      assertTrue(txt.createNewFile());

      final SitePaths site = new SitePaths(root);
      assertFalse(site.isNew);
      assertEquals(root, site.site_path);
    } finally {
      txt.delete();
      root.delete();
    }
  }

  public void testCreate_NotDirectory() throws IOException {
    final File root = random();
    try {
      assertTrue(root.createNewFile());
      try {
        new SitePaths(root);
        fail("Did not throw exception");
      } catch (FileNotFoundException e) {
        assertEquals("Not a directory: " + root.getPath(), e.getMessage());
      }
    } finally {
      root.delete();
    }
  }

  public void testResolve() throws FileNotFoundException {
    final File root = random();
    final SitePaths site = new SitePaths(root);

    assertNull(site.resolve(null));
    assertNull(site.resolve(""));

    assertNotNull(site.resolve("a"));
    assertEquals(new File(root, "a"), site.resolve("a"));

    final String pfx = isWin32() ? "C:/" : "/";
    assertNotNull(site.resolve(pfx + "a"));
    assertEquals(new File(pfx + "a"), site.resolve(pfx + "a"));
  }

  private File random() {
    final File t = new File("target");
    return new File(t, "random-name-" + UUID.randomUUID().toString());
  }

  private static boolean isWin32() {
    final String osDotName = System.getProperty("os.name");
    return osDotName != null
        && osDotName.toLowerCase().indexOf("windows") != -1;
  }
}
