summaryrefslogtreecommitdiff
path: root/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala
blob: 5dee488285c0f7b5f490ca95b6152ccaaa1d5c25 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright (c) 2014 Contributor. All rights reserved.
 */
package scala.tools.nsc.classpath

import java.io.File
import org.junit.Assert._
import org.junit._
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import scala.annotation.tailrec
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.ClassPath
import scala.tools.nsc.Settings
import scala.tools.util.FlatClassPathResolver
import scala.tools.util.PathResolver

@RunWith(classOf[JUnit4])
class FlatClassPathResolverTest {

  val tempDir = new TemporaryFolder()

  private val packagesToTest = List(FlatClassPath.RootPackage, "scala", "scala.reflect", "scala.reflect.io")
  private val classFilesToFind = List("scala.tools.util.FlatClassPathResolver",
    "scala.reflect.io.AbstractFile",
    "scala.collection.immutable.List",
    "scala.Option",
    "scala.collection.immutable.Vector",
    "scala.util.hashing.MurmurHash3",
    "java.lang.Object",
    "java.util.Date")

  private val classesToFind = classFilesToFind ++ List("TestSourceInRootPackage",
    "scala.reflect.io.TestScalaSource",
    "scala.reflect.io.TestJavaSource")

  private val settings = new Settings

  @Before
  def initTempDirAndSourcePath: Unit = {
    // In Java TemporaryFolder in JUnit is managed automatically using @Rule.
    // It would work also in Scala after adding and extending a class like
    // TestWithTempFolder.java containing it. But in this case it doesn't work when running tests
    // from the command line - java class is not compiled due to some, mysterious reasons.
    // That's why such dirs are here created and deleted manually.
    tempDir.create()
    tempDir.newFile("TestSourceInRootPackage.scala")
    val ioDir = tempDir.newFolder("scala", "reflect", "io")
    new File(ioDir, "AbstractFile.scala").createNewFile()
    new File(ioDir, "ZipArchive.java").createNewFile()
    new File(ioDir, "TestScalaSource.scala").createNewFile()
    new File(ioDir, "TestJavaSource.java").createNewFile()

    settings.usejavacp.value = true
    settings.sourcepath.value = tempDir.getRoot.getAbsolutePath
  }

  @After
  def deleteTempDir: Unit = tempDir.delete()

  private def createFlatClassPath(settings: Settings) =
    new FlatClassPathResolver(settings).result

  @Test
  def testEntriesFromListOperationAgainstSeparateMethods: Unit = {
    val classPath = createFlatClassPath(settings)

    def compareEntriesInPackage(inPackage: String): Unit = {
      val packages = classPath.packages(inPackage)
      val classes = classPath.classes(inPackage)
      val sources = classPath.sources(inPackage)
      val FlatClassPathEntries(packagesFromList, classesAndSourcesFromList) = classPath.list(inPackage)

      val packageNames = packages.map(_.name).sorted
      val packageNamesFromList = packagesFromList.map(_.name).sorted
      assertEquals(s"Methods list and packages for package '$inPackage' should return the same packages",
        packageNames, packageNamesFromList)

      val classFileNames = classes.map(_.name).sorted
      val classFileNamesFromList = classesAndSourcesFromList.filter(_.binary.isDefined).map(_.name).sorted
      assertEquals(s"Methods list and classes for package '$inPackage' should return entries for the same class files",
        classFileNames, classFileNamesFromList)

      val sourceFileNames = sources.map(_.name).sorted
      val sourceFileNamesFromList = classesAndSourcesFromList.filter(_.source.isDefined).map(_.name).sorted
      assertEquals(s"Methods list and sources for package '$inPackage' should return entries for the same source files",
        sourceFileNames, sourceFileNamesFromList)

      val uniqueNamesOfClassAndSourceFiles = (classFileNames ++ sourceFileNames).toSet
      assertEquals(s"Class and source entries with the same name obtained via list for package '$inPackage' should be merged into one containing both files",
        uniqueNamesOfClassAndSourceFiles.size, classesAndSourcesFromList.length)
    }

    packagesToTest foreach compareEntriesInPackage
  }

  @Test
  def testCreatedEntriesAgainstRecursiveClassPath: Unit = {
    val flatClassPath = createFlatClassPath(settings)
    val recursiveClassPath = new PathResolver(settings).result

    def compareEntriesInPackage(inPackage: String): Unit = {

      @tailrec
      def traverseToPackage(packageNameParts: Seq[String], cp: ClassPath[AbstractFile]): ClassPath[AbstractFile] = {
        packageNameParts match {
          case Nil => cp
          case h :: t =>
            cp.packages.find(_.name == h) match {
              case Some(nestedCp) => traverseToPackage(t, nestedCp)
              case _ => throw new Exception(s"There's no package $inPackage in recursive classpath - error when searching for '$h'")
            }
        }
      }

      val packageNameParts = if (inPackage == FlatClassPath.RootPackage) Nil else inPackage.split('.').toList
      val recursiveClassPathInPackage = traverseToPackage(packageNameParts, recursiveClassPath)

      val flatCpPackages = flatClassPath.packages(inPackage).map(_.name)
      val pkgPrefix = PackageNameUtils.packagePrefix(inPackage)
      val recursiveCpPackages = recursiveClassPathInPackage.packages.map(pkgPrefix + _.name)
      assertEquals(s"Packages in package '$inPackage' on flat cp should be the same as on the recursive cp",
        recursiveCpPackages, flatCpPackages)

      val flatCpSources = flatClassPath.sources(inPackage).map(_.name).sorted
      val recursiveCpSources = recursiveClassPathInPackage.classes
        .filter(_.source.nonEmpty)
        .map(_.name).sorted
      assertEquals(s"Source entries in package '$inPackage' on flat cp should be the same as on the recursive cp",
        recursiveCpSources, flatCpSources)

      val flatCpClasses = flatClassPath.classes(inPackage).map(_.name).sorted
      val recursiveCpClasses = recursiveClassPathInPackage.classes
        .filter(_.binary.nonEmpty)
        .map(_.name).sorted
      assertEquals(s"Class entries in package '$inPackage' on flat cp should be the same as on the recursive cp",
        recursiveCpClasses, flatCpClasses)
    }

    packagesToTest foreach compareEntriesInPackage
  }

  @Test
  def testFindClassFile: Unit = {
    val classPath = createFlatClassPath(settings)
    classFilesToFind foreach { className =>
      assertTrue(s"File for $className should be found", classPath.findClassFile(className).isDefined)
    }
  }

  @Test
  def testFindClass: Unit = {
    val classPath = createFlatClassPath(settings)
    classesToFind foreach { className =>
      assertTrue(s"File for $className should be found", classPath.findClass(className).isDefined)
    }
  }
}