• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tools.metalava
18 
19 import org.junit.Rule
20 import org.junit.Test
21 import org.junit.rules.TemporaryFolder
22 import java.io.File
23 import kotlin.test.assertEquals
24 import kotlin.test.assertTrue
25 
26 class FileReadSandboxTest {
27     @get:Rule
28     var temporaryFolder = TemporaryFolder()
29 
30     @Test
Test sandboxnull31     fun `Test sandbox`() {
32         // Create target files.
33         val root = temporaryFolder.newFolder()
34 
35         val goodFile = File(root, "goodFile").apply { createNewFile() }
36         val badFile = File(root, "badFile").apply { createNewFile() }
37 
38         val goodDir = File(root, "goodDir").apply { mkdirs() }
39         val goodDirFile = File(goodDir, "file").apply { createNewFile() }
40 
41         val badDir = File(root, "badDir").apply { mkdirs() }
42         val badDirFile = File(badDir, "file").apply { createNewFile() }
43 
44         val subDir = File(root, "subdir").apply { mkdirs() }
45         val subSubDir = File(subDir, "subdir").apply { mkdirs() }
46         val subSubDir2 = File(subDir, "subdir2").apply { mkdirs() }
47         val subSubDirGoodFile = File(subSubDir, "good").apply { createNewFile() }
48         val subSubDirBadFile = File(subSubDir, "bad").apply { createNewFile() }
49 
50         // Structure:
51         //   - *  Explicitly allowed
52         //   - ** Implicitly allowed (parent directories of allowed paths)
53         //   - @  Not allowed
54         // root        **
55         //  |-goodFile *
56         //  |
57         //  |-badFile  @
58         //  |
59         //  |-goodDir  *
60         //  |  |-goodDirFile **
61         //  |
62         //  |-badDir         @
63         //  |  |-badDirFile  @
64         //  |
65         //  |-subDir **
66         //     |-subSubDir **
67         //     |  |-subSubDirGoodFile *
68         //     |  |-subSubDirBadFile  @
69         //     |-subSubDir2           @
70 
71         // Set up the sandbox.
72         FileReadSandbox.allowAccess(goodFile)
73         FileReadSandbox.allowAccess(goodDir)
74         FileReadSandbox.allowAccess(subSubDirGoodFile)
75 
76         val allowedSet = mutableSetOf(root, goodFile, goodDir, goodDirFile, subDir, subSubDir, subSubDirGoodFile).map { it.absolutePath }
77         val emptySet = setOf<String>()
78         val violations = mutableSetOf<String>()
79 
80         // Make sure allowed files are not in the violation list.
81         fun assertAllowedFilesNotReported() {
82             assertEquals(emptySet, violations.intersect(allowedSet))
83         }
84 
85         // Assert given files are reported as violations.
86         fun assertViolationReported(vararg files: File) {
87             val fileSet = files.map { it.absolutePath }.toSet()
88             assertEquals(fileSet, violations.intersect(fileSet))
89         }
90 
91         // Assert given files are *not* reported as violations.
92         fun assertViolationNotReported(vararg files: File) {
93             val fileSet = files.map { it.absolutePath }.toSet()
94             assertEquals(emptySet, violations.intersect(fileSet))
95         }
96 
97         val listener = object : FileReadSandbox.Listener {
98             override fun onViolation(absolutePath: String, isDirectory: Boolean) {
99                 violations.add(absolutePath)
100             }
101         }
102 
103         // Activate the sandbox.
104         FileReadSandbox.activate(listener)
105         try {
106             // Access "good" files, which should be allowed.
107             goodFile.readBytes()
108             subSubDirGoodFile.readBytes()
109 
110             // If a file is created by metalava, then it can be read.
111             val newFile1 = File(root, "newFile1").apply { createNewFile() }
112             newFile1.readBytes()
113 
114             assertAllowedFilesNotReported()
115             assertViolationNotReported(badFile, badDir, badDirFile, subSubDirBadFile)
116 
117             // Access "bad" files.
118             badFile.readBytes()
119             badDirFile.readBytes()
120 
121             assertAllowedFilesNotReported()
122             assertViolationReported(badFile, badDirFile)
123             assertViolationNotReported(subSubDirBadFile)
124 
125             // Clear the violations, and access badDir.
126             violations.clear()
127             badDir.listFiles()
128             root.listFiles()
129 
130             assertAllowedFilesNotReported()
131             assertViolationReported(badDir)
132             assertViolationNotReported(badFile, badDirFile, subSubDirBadFile)
133 
134             // Check "implicitly allowed access" directories.
135             violations.clear()
136             subDir.listFiles() // Implicitly allowed.
137             subSubDir.listFiles() // Implicitly allowed.
138             subSubDir2.listFiles() // *Not* implicitly allowed.
139             subSubDirGoodFile.readBytes()
140             subSubDirBadFile.readBytes() // *Not* allowed.
141             root.listFiles()
142 
143             assertAllowedFilesNotReported()
144 
145             assertViolationReported(subSubDir2, subSubDirBadFile) // These are not allowed to read.
146         } finally {
147             // Deactivate the sandbox.
148             FileReadSandbox.deactivate()
149             FileReadSandbox.reset()
150         }
151         violations.clear()
152 
153         // This shouldn't trigger the listener.
154         badFile.readBytes()
155 
156         assertTrue(violations.isEmpty())
157     }
158 }
159