• 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 dirctories of whitelisted 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         var allowedSet = mutableSetOf(root, goodFile, goodDir, goodDirFile, subDir, subSubDir, subSubDirGoodFile).map { it.absolutePath }
77         var emptySet = setOf<String>()
78 
79         var violations = mutableSetOf<String>()
80 
81         // Make sure whitelisted files are not in the violation list.
82         fun assertWhitelistedFilesNotReported() {
83             assertEquals(emptySet, violations.intersect(allowedSet))
84         }
85 
86         // Assert given files are reported as violations.
87         fun assertViolationReported(vararg files: File) {
88             val fileSet = files.map { it.absolutePath }.toSet()
89             assertEquals(fileSet, violations.intersect(fileSet))
90         }
91 
92         // Assert given files are *not* reported as violations.
93         fun assertViolationNotReported(vararg files: File) {
94             val fileSet = files.map { it.absolutePath }.toSet()
95             assertEquals(emptySet, violations.intersect(fileSet))
96         }
97 
98         val listener = object : FileReadSandbox.Listener {
99             override fun onViolation(absolutePath: String, isDirectory: Boolean) {
100                 violations.add(absolutePath)
101             }
102         }
103 
104         // Activate the sandbox.
105         FileReadSandbox.activate(listener)
106         try {
107             // Access "good" files, which should be allowed.
108             goodFile.readBytes()
109             subSubDirGoodFile.readBytes()
110 
111             // If a file is created by metalava, then it can be read.
112             val newFile1 = File(root, "newFile1").apply { createNewFile() }
113             newFile1.readBytes()
114 
115             assertWhitelistedFilesNotReported()
116             assertViolationNotReported(badFile, badDir, badDirFile, subSubDirBadFile)
117 
118             // Access "bad" files.
119             badFile.readBytes()
120             badDirFile.readBytes()
121 
122             assertWhitelistedFilesNotReported()
123             assertViolationReported(badFile, badDirFile)
124             assertViolationNotReported(subSubDirBadFile)
125 
126             // Clear the violations, and access badDir.
127             violations.clear()
128             badDir.listFiles()
129             root.listFiles()
130 
131             assertWhitelistedFilesNotReported()
132             assertViolationReported(badDir)
133             assertViolationNotReported(badFile, badDirFile, subSubDirBadFile)
134 
135             // Check "implicitly allowed access" directories.
136             violations.clear()
137             subDir.listFiles() // Implicitly allowed.
138             subSubDir.listFiles() // Implicitly allowed.
139             subSubDir2.listFiles() // *Not* implicitly allowed.
140             subSubDirGoodFile.readBytes()
141             subSubDirBadFile.readBytes() // *Not* allowed.
142             root.listFiles()
143 
144             assertWhitelistedFilesNotReported()
145 
146             assertViolationReported(subSubDir2, subSubDirBadFile) // These are not allowed to read.
147         } finally {
148             // Deactivate the sandbox.
149             FileReadSandbox.deactivate()
150             FileReadSandbox.reset()
151         }
152         violations.clear()
153 
154         // This shouldn't trigger the listener.
155         badFile.readBytes()
156 
157         assertTrue(violations.isEmpty())
158     }
159 }
160