/*
 * Copyright 2020 Google LLC.
 *
 * 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.cloud.tools.opensource.classpath;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import com.google.cloud.tools.opensource.dependencies.RepositoryUtility;
import com.google.common.collect.ImmutableSet;
import com.google.common.testing.EqualsTester;
import com.google.common.truth.Truth;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.junit.Test;

public class ClassPathEntryTest {
  Path fooJar = Paths.get("foo.jar");
  Path barJar = Paths.get("bar.jar");
  private Artifact fooArtifact =
      new DefaultArtifact("com.google", "foo", null, "jar", "0.0.1", null, fooJar.toFile());
  private Artifact barArtifact =
      new DefaultArtifact("com.google", "bar", null, "jar", "0.0.1", null, barJar.toFile());

  @Test
  public void testCreationJar() {
    Path jar = Paths.get("foo.jar");
    ClassPathEntry entry = new ClassPathEntry(jar);
    assertEquals(jar, entry.getJar());
    assertNull(entry.getArtifact());
  }

  @Test
  public void testCreationArtifact() {
    ClassPathEntry entry = new ClassPathEntry(fooArtifact);
    assertEquals(fooJar, entry.getJar());
    assertEquals(entry.getArtifact(), fooArtifact);
  }

  @Test
  public void testEquality() {
    Path jar1 = Paths.get("1.jar");
    Path jar2 = Paths.get("2.jar");
    new EqualsTester()
        .addEqualityGroup(new ClassPathEntry(jar1), new ClassPathEntry(jar1))
        .addEqualityGroup(new ClassPathEntry(jar2), new ClassPathEntry(jar2))
        .addEqualityGroup(new ClassPathEntry(fooArtifact), new ClassPathEntry(fooArtifact))
        .addEqualityGroup(new ClassPathEntry(barArtifact), new ClassPathEntry(barArtifact))
        .addEqualityGroup(
            new ClassPathEntry(
                new DefaultArtifact(null, null, null, null, null, null, jar1.toFile())))
        .testEquals();
  }

  @Test
  public void testToStringJar() {
    Path fooJar = Paths.get("foo.jar");
    ClassPathEntry entry = new ClassPathEntry(fooJar);
    assertEquals("foo.jar", entry.toString());
  }

  @Test
  public void testToStringArtifact() {
    ClassPathEntry entry = new ClassPathEntry(fooArtifact);
    assertEquals("com.google:foo:0.0.1", entry.toString());
  }

  @Test
  public void testListFileNames() throws IOException, ArtifactResolutionException {
 
    // copy into the local repository so we can read the jar file
    Artifact artifact = resolveArtifact("com.google.truth.extensions:truth-java8-extension:1.0.1");
    
    ClassPathEntry entry = new ClassPathEntry(artifact);
    ImmutableSet<String> classFileNames = entry.listClassFileNames();
    Truth.assertThat(classFileNames).containsExactly(
        "com.google.common.truth.IntStreamSubject",
        "com.google.common.truth.LongStreamSubject",
        "com.google.common.truth.OptionalDoubleSubject",
        "com.google.common.truth.OptionalSubject",
        "com.google.common.truth.OptionalIntSubject",
        "com.google.common.truth.OptionalLongSubject",
        "com.google.common.truth.PathSubject",
        "com.google.common.truth.Truth8",
        "com.google.common.truth.StreamSubject");
  }
  
  @Test
  public void testListFileNames_innerClasses()
      throws IOException, ArtifactResolutionException, URISyntaxException {

    ClassPathEntry entry = TestHelper.classPathEntryOfResource(
        "testdata/conscrypt-openjdk-uber-1.4.2.jar");
    
    ImmutableSet<String> classFileNames = entry.listClassFileNames();
    Truth.assertThat(classFileNames).containsAtLeast(
        "org.conscrypt.OpenSSLSignature$1",
        "org.conscrypt.OpenSSLContextImpl$TLSv1",
        "org.conscrypt.TrustManagerImpl$1",
        "org.conscrypt.PeerInfoProvider",
        "org.conscrypt.PeerInfoProvider$1",
        "org.conscrypt.ExternalSession$Provider",
        "org.conscrypt.OpenSSLMac");
  }

  private static Artifact resolveArtifact(String coords) throws ArtifactResolutionException {
    RepositorySystem system = RepositoryUtility.newRepositorySystem();
    RepositorySystemSession session = RepositoryUtility.newSession(system);

    Artifact artifact = new DefaultArtifact(coords);    
    ArtifactRequest artifactRequest = new ArtifactRequest();
    artifactRequest.setArtifact(artifact);
    ArtifactResult artifactResult = system.resolveArtifact(session, artifactRequest);
    
    return artifactResult.getArtifact();
  }
  
  @Test
  public void testFilePresenceRequirement() {
    Artifact artifactWithoutFile = new DefaultArtifact("com.google:foo:jar:1.0.0");
    try {
      new ClassPathEntry(artifactWithoutFile);
      fail();
    } catch (NullPointerException expected) {
      // pass
    }
  }
}

@@ -1092,16 +1092,41 @@
 .Paths;%0A
+import java.util.Locale;%0A
 import o
@@ -1482,16 +1482,41 @@
 Result;%0A
+import org.junit.Assert;%0A
 import o
@@ -3415,18 +3415,16 @@
 ption %7B%0A
- %0A
     // c
@@ -4924,24 +4924,573 @@
 SLMac%22);%0A  %7D
+%0A  %0A  @Test%0A  public void testListFileNames_noManifest()%0A      throws IOException, ArtifactResolutionException, URISyntaxException %7B%0A%0A    ClassPathEntry entry = TestHelper.classPathEntryOfResource(%0A        %22testdata/conscrypt-openjdk-uber-1.4.2.jar%22);%0A    %0A    ImmutableSet%3CString%3E classFileNames = entry.listClassFileNames();%0A    for (String filename : classFileNames) %7B%0A      Assert.assertFalse(filename.toLowerCase(Locale.ENGLISH).contains(%22manifest%22));%0A      Assert.assertFalse(filename.toLowerCase(Locale.ENGLISH).contains(%22meta%22));%0A    %7D  %0A  %7D
 %0A%0A  private 
@@ -5533,16 +5533,21 @@
 ng coord
+inate
 s) throw
@@ -5775,16 +5775,21 @@
 ct(coord
+inate
 s);    %0A
@@ -6290,22 +6290,8 @@
 ) %7B%0A
-      // pass%0A
     

make sure we don't accidentaly read MANIFEST.MF as a .class file (#1326)