• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 com.android.tools.metalava.model.defaultConfiguration
20 import org.junit.Assert.assertEquals
21 import org.junit.Assert.assertFalse
22 import org.junit.Assert.assertTrue
23 import org.junit.Test
24 import java.io.File
25 import java.io.PrintWriter
26 import java.io.StringWriter
27 
28 @Suppress("PrivatePropertyName")
29 class OptionsTest : DriverTest() {
30     private val DESCRIPTION = """
31 $PROGRAM_NAME extracts metadata from source code to generate artifacts such as the signature files, the SDK stub files,
32 external annotations etc.
33 """.trimIndent()
34 
35     private val FLAGS = """
36 Usage: metalava <flags>
37 
38 
39 General:
40 --help
41                                              This message.
42 --version
43                                              Show the version of metalava.
44 --quiet
45                                              Only include vital output
46 --verbose
47                                              Include extra diagnostic output
48 --color
49                                              Attempt to colorize the output (defaults to true if ${"$"}TERM is xterm)
50 --no-color
51                                              Do not attempt to colorize the output
52 --no-docs
53                                              Cancel any other documentation flags supplied to metalava. This is here to
54                                              make it easier customize build system tasks.
55 --only-update-api
56                                              Cancel any other "action" flags other than generating signature files. This
57                                              is here to make it easier customize build system tasks, particularly for
58                                              the "make update-api" task.
59 --only-check-api
60                                              Cancel any other "action" flags other than checking signature files. This
61                                              is here to make it easier customize build system tasks, particularly for
62                                              the "make checkapi" task.
63 --repeat-errors-max <N>
64                                              When specified, repeat at most N errors before finishing.
65 
66 
67 API sources:
68 --source-files <files>
69                                              A comma separated list of source files to be parsed. Can also be @ followed
70                                              by a path to a text file containing paths to the full set of files to
71                                              parse.
72 --source-path <paths>
73                                              One or more directories (separated by `:`) containing source files (within
74                                              a package hierarchy). If --strict-input-files, --strict-input-files:warn,
75                                              or --strict-input-files:stack are used, files accessed under --source-path
76                                              that are not explicitly specified in --source-files are reported as
77                                              violations.
78 --classpath <paths>
79                                              One or more directories or jars (separated by `:`) containing classes that
80                                              should be on the classpath when parsing the source files
81 --merge-qualifier-annotations <file>
82                                              An external annotations file to merge and overlay the sources, or a
83                                              directory of such files. Should be used for annotations intended for
84                                              inclusion in the API to be written out, e.g. nullability. Formats supported
85                                              are: IntelliJ's external annotations database format, .jar or .zip files
86                                              containing those, Android signature files, and Java stub files.
87 --merge-inclusion-annotations <file>
88                                              An external annotations file to merge and overlay the sources, or a
89                                              directory of such files. Should be used for annotations which determine
90                                              inclusion in the API to be written out, i.e. show and hide. The only format
91                                              supported is Java stub files.
92 --validate-nullability-from-merged-stubs
93                                              Triggers validation of nullability annotations for any class where
94                                              --merge-qualifier-annotations includes a Java stub file.
95 --validate-nullability-from-list
96                                              Triggers validation of nullability annotations for any class listed in the
97                                              named file (one top-level class per line, # prefix for comment line).
98 --nullability-warnings-txt <file>
99                                              Specifies where to write warnings encountered during validation of
100                                              nullability annotations. (Does not trigger validation by itself.)
101 --nullability-errors-non-fatal
102                                              Specifies that errors encountered during validation of nullability
103                                              annotations should not be treated as errors. They will be written out to
104                                              the file specified in --nullability-warnings-txt instead.
105 --input-api-jar <file>
106                                              A .jar file to read APIs from directly
107 --manifest <file>
108                                              A manifest file, used to for check permissions to cross check APIs
109 --replace-documentation <p> <r> <t>
110                                              Amongst nonempty documentation of items from Java packages <p> and their
111                                              subpackages, replaces any matches of regular expression <r> with
112                                              replacement text <t>. <p> is given as a nonempty list of Java package names
113                                              separated by ':' (e.g. "java:android.util"); <t> may contain backreferences
114                                              ($1, $2 etc.) to matching groups from <r>.
115 --hide-package <package>
116                                              Remove the given packages from the API even if they have not been marked
117                                              with @hide
118 --show-annotation <annotation class>
119                                              Unhide any hidden elements that are also annotated with the given
120                                              annotation
121 --show-single-annotation <annotation>
122                                              Like --show-annotation, but does not apply to members; these must also be
123                                              explicitly annotated
124 --show-for-stub-purposes-annotation <annotation class>
125                                              Like --show-annotation, but elements annotated with it are assumed to be
126                                              "implicitly" included in the API surface, and they'll be included in
127                                              certain kinds of output such as stubs, but not in others, such as the
128                                              signature file and API lint
129 --hide-annotation <annotation class>
130                                              Treat any elements annotated with the given annotation as hidden
131 --hide-meta-annotation <meta-annotation class>
132                                              Treat as hidden any elements annotated with an annotation which is itself
133                                              annotated with the given meta-annotation
134 --show-unannotated
135                                              Include un-annotated public APIs in the signature file as well
136 --java-source <level>
137                                              Sets the source level for Java source files; default is 1.8.
138 --kotlin-source <level>
139                                              Sets the source level for Kotlin source files; default is 1.4.
140 --sdk-home <dir>
141                                              If set, locate the `android.jar` file from the given Android SDK
142 --compile-sdk-version <api>
143                                              Use the given API level
144 --jdk-home <dir>
145                                              If set, add the Java APIs from the given JDK to the classpath
146 --stub-packages <package-list>
147                                              List of packages (separated by :) which will be used to filter out
148                                              irrelevant code. If specified, only code in these packages will be included
149                                              in signature files, stubs, etc. (This is not limited to just the stubs; the
150                                              name is historical.) You can also use ".*" at the end to match subpackages,
151                                              so `foo.*` will match both `foo` and `foo.bar`.
152 --subtract-api <api file>
153                                              Subtracts the API in the given signature or jar file from the current API
154                                              being emitted via --api, --stubs, --doc-stubs, etc. Note that the
155                                              subtraction only applies to classes; it does not subtract members.
156 --typedefs-in-signatures <ref|inline>
157                                              Whether to include typedef annotations in signature files.
158                                              `--typedefs-in-signatures ref` will include just a reference to the typedef
159                                              class, which is not itself part of the API and is not included as a class,
160                                              and `--typedefs-in-signatures inline` will include the constants themselves
161                                              into each usage site. You can also supply `--typedefs-in-signatures none`
162                                              to explicitly turn it off, if the default ever changes.
163 --ignore-classes-on-classpath
164                                              Prevents references to classes on the classpath from being added to the
165                                              generated stub files.
166 
167 
168 Documentation:
169 --public
170                                              Only include elements that are public
171 --protected
172                                              Only include elements that are public or protected
173 --package
174                                              Only include elements that are public, protected or package protected
175 --private
176                                              Include all elements except those that are marked hidden
177 --hidden
178                                              Include all elements, including hidden
179 
180 
181 Extracting Signature Files:
182 --api <file>
183                                              Generate a signature descriptor file
184 --dex-api <file>
185                                              Generate a DEX signature descriptor file listing the APIs
186 --removed-api <file>
187                                              Generate a signature descriptor file for APIs that have been removed
188 --format=<v1,v2,v3,...>
189                                              Sets the output signature file format to be the given version.
190 --output-kotlin-nulls[=yes|no]
191                                              Controls whether nullness annotations should be formatted as in Kotlin
192                                              (with "?" for nullable types, "" for non nullable types, and "!" for
193                                              unknown. The default is yes.
194 --output-default-values[=yes|no]
195                                              Controls whether default values should be included in signature files. The
196                                              default is yes.
197 --compatible-output=[yes|no]
198                                              Controls whether to keep signature files compatible with the historical
199                                              format (with its various quirks) or to generate the new format (which will
200                                              also include annotations that are part of the API, etc.)
201 --omit-common-packages[=yes|no]
202                                              Skip common package prefixes like java.lang.* and kotlin.* in signature
203                                              files, along with packages for well known annotations like @Nullable and
204                                              @NonNull.
205 --include-signature-version[=yes|no]
206                                              Whether the signature files should include a comment listing the format
207                                              version of the signature file.
208 --proguard <file>
209                                              Write a ProGuard keep file for the API
210 --sdk-values <dir>
211                                              Write SDK values files to the given directory
212 
213 
214 Generating Stubs:
215 --stubs <dir>
216                                              Generate stub source files for the API
217 --doc-stubs <dir>
218                                              Generate documentation stub source files for the API. Documentation stub
219                                              files are similar to regular stub files, but there are some differences.
220                                              For example, in the stub files, we'll use special annotations like
221                                              @RecentlyNonNull instead of @NonNull to indicate that an element is
222                                              recently marked as non null, whereas in the documentation stubs we'll just
223                                              list this as @NonNull. Another difference is that @doconly elements are
224                                              included in documentation stubs, but not regular stubs, etc.
225 --kotlin-stubs
226                                              [CURRENTLY EXPERIMENTAL] If specified, stubs generated from Kotlin source
227                                              code will be written in Kotlin rather than the Java programming language.
228 --include-annotations
229                                              Include annotations such as @Nullable in the stub files.
230 --exclude-all-annotations
231                                              Exclude annotations such as @Nullable from the stub files; the default.
232 --pass-through-annotation <annotation classes>
233                                              A comma separated list of fully qualified names of annotation classes that
234                                              must be passed through unchanged.
235 --exclude-annotation <annotation classes>
236                                              A comma separated list of fully qualified names of annotation classes that
237                                              must be stripped from metalava's outputs.
238 --exclude-documentation-from-stubs
239                                              Exclude element documentation (javadoc and kdoc) from the generated stubs.
240                                              (Copyright notices are not affected by this, they are always included.
241                                              Documentation stubs (--doc-stubs) are not affected.)
242 --write-stubs-source-list <file>
243                                              Write the list of generated stub files into the given source list file. If
244                                              generating documentation stubs and you haven't also specified
245                                              --write-doc-stubs-source-list, this list will refer to the documentation
246                                              stubs; otherwise it's the non-documentation stubs.
247 --write-doc-stubs-source-list <file>
248                                              Write the list of generated doc stub files into the given source list file
249 --register-artifact <api-file> <id>
250                                              Registers the given id for the packages found in the given signature file.
251                                              metalava will inject an @artifactId <id> tag into every top level stub
252                                              class in that API.
253 
254 
255 Diffs and Checks:
256 --input-kotlin-nulls[=yes|no]
257                                              Whether the signature file being read should be interpreted as having
258                                              encoded its types using Kotlin style types: a suffix of "?" for nullable
259                                              types, no suffix for non nullable types, and "!" for unknown. The default
260                                              is no.
261 --check-compatibility:type:state <file>
262                                              Check compatibility. Type is one of 'api' and 'removed', which checks
263                                              either the public api or the removed api. State is one of 'current' and
264                                              'released', to check either the currently in development API or the last
265                                              publicly released API, respectively. Different compatibility checks apply
266                                              in the two scenarios. For example, to check the code base against the
267                                              current public API, use --check-compatibility:api:current.
268 --check-compatibility:base <file>
269                                              When performing a compat check, use the provided signature file as a base
270                                              api, which is treated as part of the API being checked. This allows us to
271                                              compute the full API surface from a partial API surface (e.g. the current
272                                              @SystemApi txt file), which allows us to recognize when an API is moved
273                                              from the partial API to the base API and avoid incorrectly flagging this as
274                                              an API removal.
275 --api-lint [api file]
276                                              Check API for Android API best practices. If a signature file is provided,
277                                              only the APIs that are new since the API will be checked.
278 --api-lint-ignore-prefix [prefix]
279                                              A list of package prefixes to ignore API issues in when running with
280                                              --api-lint.
281 --migrate-nullness <api file>
282                                              Compare nullness information with the previous stable API and mark newly
283                                              annotated APIs as under migration.
284 --warnings-as-errors
285                                              Promote all warnings to errors
286 --lints-as-errors
287                                              Promote all API lint warnings to errors
288 --error <id>
289                                              Report issues of the given id as errors
290 --warning <id>
291                                              Report issues of the given id as warnings
292 --lint <id>
293                                              Report issues of the given id as having lint-severity
294 --hide <id>
295                                              Hide/skip issues of the given id
296 --report-even-if-suppressed <file>
297                                              Write all issues into the given file, even if suppressed (via annotation or
298                                              baseline) but not if hidden (by '--hide')
299 --baseline <file>
300                                              Filter out any errors already reported in the given baseline file, or
301                                              create if it does not already exist
302 --update-baseline [file]
303                                              Rewrite the existing baseline file with the current set of warnings. If
304                                              some warnings have been fixed, this will delete them from the baseline
305                                              files. If a file is provided, the updated baseline is written to the given
306                                              file; otherwise the original source baseline file is updated.
307 --baseline:api-lint <file> --update-baseline:api-lint [file]
308                                              Same as --baseline and --update-baseline respectively, but used
309                                              specifically for API lint issues performed by --api-lint.
310 --baseline:compatibility:released <file> --update-baseline:compatibility:released [file]
311                                              Same as --baseline and --update-baseline respectively, but used
312                                              specifically for API compatibility issues performed by
313                                              --check-compatibility:api:released and
314                                              --check-compatibility:removed:released.
315 --merge-baseline [file]
316                                              Like --update-baseline, but instead of always replacing entries in the
317                                              baseline, it will merge the existing baseline with the new baseline. This
318                                              is useful if metalava runs multiple times on the same source tree with
319                                              different flags at different times, such as occasionally with --api-lint.
320 --pass-baseline-updates
321                                              Normally, encountering error will fail the build, even when updating
322                                              baselines. This flag allows you to tell metalava to continue without
323                                              errors, such that all the baselines in the source tree can be updated in
324                                              one go.
325 --delete-empty-baselines
326                                              Whether to delete baseline files if they are updated and there is nothing
327                                              to include.
328 --error-message:api-lint <message>
329                                              If set, metalava shows it when errors are detected in --api-lint.
330 --error-message:compatibility:released <message>
331                                              If set, metalava shows it when errors are detected in
332                                              --check-compatibility:api:released and
333                                              --check-compatibility:removed:released.
334 --error-message:compatibility:current <message>
335                                              If set, metalava shows it when errors are detected in
336                                              --check-compatibility:api:current and
337                                              --check-compatibility:removed:current.
338 
339 
340 JDiff:
341 --api-xml <file>
342                                              Like --api, but emits the API in the JDiff XML format instead
343 --convert-to-jdiff <sig> <xml>
344                                              Reads in the given signature file, and writes it out in the JDiff XML
345                                              format. Can be specified multiple times.
346 --convert-new-to-jdiff <old> <new> <xml>
347                                              Reads in the given old and new api files, computes the difference, and
348                                              writes out only the new parts of the API in the JDiff XML format.
349 --convert-to-v1 <sig> <sig>
350                                              Reads in the given signature file and writes it out as a signature file in
351                                              the original v1/doclava format.
352 --convert-to-v2 <sig> <sig>
353                                              Reads in the given signature file and writes it out as a signature file in
354                                              the new signature format, v2.
355 --convert-new-to-v2 <old> <new> <sig>
356                                              Reads in the given old and new api files, computes the difference, and
357                                              writes out only the new parts of the API in the v2 format.
358 
359 
360 Statistics:
361 --annotation-coverage-stats
362                                              Whether metalava should emit coverage statistics for annotations, listing
363                                              the percentage of the API that has been annotated with nullness
364                                              information.
365 --annotation-coverage-of <paths>
366                                              One or more jars (separated by `:`) containing existing apps that we want
367                                              to measure annotation coverage statistics for. The set of API usages in
368                                              those apps are counted up and the most frequently used APIs that are
369                                              missing annotation metadata are listed in descending order.
370 --skip-java-in-coverage-report
371                                              In the coverage annotation report, skip java.** and kotlin.** to narrow the
372                                              focus down to the Android framework APIs.
373 --write-class-coverage-to <path>
374                                              Specifies a file to write the annotation coverage report for classes to.
375 --write-member-coverage-to <path>
376                                              Specifies a file to write the annotation coverage report for members to.
377 
378 
379 Extracting Annotations:
380 --extract-annotations <zipfile>
381                                              Extracts source annotations from the source files and writes them into the
382                                              given zip file
383 --include-annotation-classes <dir>
384                                              Copies the given stub annotation source files into the generated stub
385                                              sources; <dir> is typically metalava/stub-annotations/src/main/java/.
386 --rewrite-annotations <dir/jar>
387                                              For a bytecode folder or output jar, rewrites the androidx annotations to
388                                              be package private
389 --force-convert-to-warning-nullability-annotations <package1:-package2:...>
390                                              On every API declared in a class referenced by the given filter, makes
391                                              nullability issues appear to callers as warnings rather than errors by
392                                              replacing @Nullable/@NonNull in these APIs with
393                                              @RecentlyNullable/@RecentlyNonNull
394 --copy-annotations <source> <dest>
395                                              For a source folder full of annotation sources, generates corresponding
396                                              package private versions of the same annotations.
397 --include-source-retention
398                                              If true, include source-retention annotations in the stub files. Does not
399                                              apply to signature files. Source retention annotations are extracted into
400                                              the external annotations files instead.
401 
402 
403 Injecting API Levels:
404 --apply-api-levels <api-versions.xml>
405                                              Reads an XML file containing API level descriptions and merges the
406                                              information into the documentation
407 
408 
409 Extracting API Levels:
410 --generate-api-levels <xmlfile>
411                                              Reads android.jar SDK files and generates an XML file recording the API
412                                              level for each class, method and field
413 --android-jar-pattern <pattern>
414                                              Patterns to use to locate Android JAR files. The default is
415                                              ${"$"}ANDROID_HOME/platforms/android-%/android.jar.
416 --current-version
417                                              Sets the current API level of the current source code
418 --current-codename
419                                              Sets the code name for the current source code
420 --current-jar
421                                              Points to the current API jar, if any
422 
423 
424 Sandboxing:
425 --no-implicit-root
426                                              Disable implicit root directory detection. Otherwise, metalava adds in
427                                              source roots implied by the source files
428 --strict-input-files <file>
429                                              Do not read files that are not explicitly specified in the command line.
430                                              All violations are written to the given file. Reads on directories are
431                                              always allowed, but metalava still tracks reads on directories that are not
432                                              specified in the command line, and write them to the file.
433 --strict-input-files:warn <file>
434                                              Warn when files not explicitly specified on the command line are read. All
435                                              violations are written to the given file. Reads on directories not
436                                              specified in the command line are allowed but also logged.
437 --strict-input-files:stack <file>
438                                              Same as --strict-input-files but also print stacktraces.
439 --strict-input-files-exempt <files or dirs>
440                                              Used with --strict-input-files. Explicitly allow access to files and/or
441                                              directories (separated by `:). Can also be @ followed by a path to a text
442                                              file containing paths to the full set of files and/or directories.
443 
444 
445 Environment Variables:
446 METALAVA_DUMP_ARGV
447                                              Set to true to have metalava emit all the arguments it was invoked with.
448                                              Helpful when debugging or reproducing under a debugger what the build
449                                              system is doing.
450 METALAVA_PREPEND_ARGS
451                                              One or more arguments (concatenated by space) to insert into the command
452                                              line, before the documentation flags.
453 METALAVA_APPEND_ARGS
454                                              One or more arguments (concatenated by space) to append to the end of the
455                                              command line, after the generate documentation flags.
456 
457 """.trimIndent()
458 
459     @Test
Test invalid argumentsnull460     fun `Test invalid arguments`() {
461         val args = listOf(ARG_NO_COLOR, "--blah-blah-blah")
462 
463         val stdout = StringWriter()
464         val stderr = StringWriter()
465         run(
466             originalArgs = args.toTypedArray(),
467             stdout = PrintWriter(stdout),
468             stderr = PrintWriter(stderr)
469         )
470         assertEquals(BANNER + "\n\n", stdout.toString())
471         assertEquals(
472             """
473 
474 Aborting: Invalid argument --blah-blah-blah
475 
476 $FLAGS
477 
478 """.trimIndent(), stderr.toString()
479         )
480     }
481 
482     @Test
Test helpnull483     fun `Test help`() {
484         val args = listOf(ARG_NO_COLOR, "--help")
485 
486         val stdout = StringWriter()
487         val stderr = StringWriter()
488         run(
489             originalArgs = args.toTypedArray(),
490             stdout = PrintWriter(stdout),
491             stderr = PrintWriter(stderr)
492         )
493         assertEquals("", stderr.toString())
494         assertEquals(
495             """
496 $BANNER
497 
498 
499 $DESCRIPTION
500 
501 $FLAGS
502 
503 """.trimIndent(), stdout.toString()
504         )
505     }
506 
507     @Test
Test issue severity optionsnull508     fun `Test issue severity options`() {
509         check(
510             extraArguments = arrayOf(
511                 "--hide",
512                 "StartWithLower",
513                 "--lint",
514                 "EndsWithImpl",
515                 "--warning",
516                 "StartWithUpper",
517                 "--error",
518                 "ArrayReturn"
519             )
520         )
521         assertEquals(Severity.HIDDEN, defaultConfiguration.getSeverity(Issues.START_WITH_LOWER))
522         assertEquals(Severity.LINT, defaultConfiguration.getSeverity(Issues.ENDS_WITH_IMPL))
523         assertEquals(Severity.WARNING, defaultConfiguration.getSeverity(Issues.START_WITH_UPPER))
524         assertEquals(Severity.ERROR, defaultConfiguration.getSeverity(Issues.ARRAY_RETURN))
525     }
526 
527     @Test
Test multiple issue severity optionsnull528     fun `Test multiple issue severity options`() {
529         check(
530             extraArguments = arrayOf("--hide", "StartWithLower,StartWithUpper,ArrayReturn")
531         )
532         assertEquals(Severity.HIDDEN, defaultConfiguration.getSeverity(Issues.START_WITH_LOWER))
533         assertEquals(Severity.HIDDEN, defaultConfiguration.getSeverity(Issues.START_WITH_UPPER))
534         assertEquals(Severity.HIDDEN, defaultConfiguration.getSeverity(Issues.ARRAY_RETURN))
535     }
536 
537     @Test
Test issue severity options with inheriting issuesnull538     fun `Test issue severity options with inheriting issues`() {
539         check(
540             extraArguments = arrayOf("--error", "RemovedClass")
541         )
542         assertEquals(Severity.ERROR, defaultConfiguration.getSeverity(Issues.REMOVED_CLASS))
543         assertEquals(Severity.ERROR, defaultConfiguration.getSeverity(Issues.REMOVED_DEPRECATED_CLASS))
544     }
545 
546     @Test
Test issue severity options with case insensitive namesnull547     fun `Test issue severity options with case insensitive names`() {
548         check(
549             extraArguments = arrayOf("--hide", "arrayreturn"),
550             expectedIssues = "warning: Case-insensitive issue matching is deprecated, use --hide ArrayReturn instead of --hide arrayreturn [DeprecatedOption]"
551         )
552         assertEquals(Severity.HIDDEN, defaultConfiguration.getSeverity(Issues.ARRAY_RETURN))
553     }
554 
555     @Test
Test issue severity options with non-existing issuenull556     fun `Test issue severity options with non-existing issue`() {
557         check(
558             extraArguments = arrayOf("--hide", "ThisIssueDoesNotExist"),
559             expectedFail = "Aborting: Unknown issue id: --hide ThisIssueDoesNotExist"
560         )
561     }
562 
563     @Test
Test for --strict-input-files-exemptnull564     fun `Test for --strict-input-files-exempt`() {
565         val top = temporaryFolder.newFolder()
566 
567         val dir = File(top, "childdir").apply { mkdirs() }
568         val grandchild1 = File(dir, "grandchiild1").apply { createNewFile() }
569         val grandchild2 = File(dir, "grandchiild2").apply { createNewFile() }
570         val file1 = File(top, "file1").apply { createNewFile() }
571         val file2 = File(top, "file2").apply { createNewFile() }
572 
573         try {
574             check(
575                 extraArguments = arrayOf("--strict-input-files-exempt",
576                     file1.path + File.pathSeparatorChar + dir.path)
577             )
578 
579             assertTrue(FileReadSandbox.isAccessAllowed(file1))
580             assertTrue(FileReadSandbox.isAccessAllowed(grandchild1))
581             assertTrue(FileReadSandbox.isAccessAllowed(grandchild2))
582 
583             assertFalse(FileReadSandbox.isAccessAllowed(file2)) // Access *not* allowed
584         } finally {
585             FileReadSandbox.reset()
586         }
587     }
588 }
589