blob: 4b3b697150285f34e5d36146c13ff2258acf09e5 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.vfs;
15
16import static com.google.common.truth.Truth.assertThat;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010017import static org.junit.Assert.fail;
18
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.Lists;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.devtools.build.lib.util.BlazeClock;
22import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
23
24import org.junit.Before;
25import org.junit.Test;
26import org.junit.runner.RunWith;
27import org.junit.runners.JUnit4;
28
29import java.util.Collection;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import java.util.HashSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010031import java.util.Set;
32
33/**
34 * Tests {@link UnixGlob} recursive globs.
35 */
36@RunWith(JUnit4.class)
37public class RecursiveGlobTest {
38
39 private Path tmpPath;
40 private FileSystem fileSystem;
41
42 @Before
Florian Weikert99ac0a22015-12-01 15:05:35 +000043 public final void initializeFileSystem() throws Exception {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044 fileSystem = new InMemoryFileSystem(BlazeClock.instance());
45 tmpPath = fileSystem.getPath("/rglobtmp");
46 for (String dir : ImmutableList.of("foo/bar/wiz",
47 "foo/baz/wiz",
48 "foo/baz/quip/wiz",
49 "food/baz/wiz",
50 "fool/baz/wiz")) {
51 FileSystemUtils.createDirectoryAndParents(tmpPath.getRelative(dir));
52 }
53 FileSystemUtils.createEmptyFile(tmpPath.getRelative("foo/bar/wiz/file"));
54 }
55
56 @Test
57 public void testDoubleStar() throws Exception {
58 assertGlobMatches("**", ".", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", "foo/baz/quip",
59 "foo/baz/quip/wiz", "foo/baz/wiz", "foo/bar/wiz/file", "food", "food/baz",
60 "food/baz/wiz", "fool", "fool/baz", "fool/baz/wiz");
61 }
62
63 @Test
64 public void testDoubleDoubleStar() throws Exception {
65 assertGlobMatches("**/**", ".", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", "foo/baz/quip",
66 "foo/baz/quip/wiz", "foo/baz/wiz", "foo/bar/wiz/file", "food", "food/baz",
67 "food/baz/wiz", "fool", "fool/baz", "fool/baz/wiz");
68 }
69
70 @Test
71 public void testDirectoryWithDoubleStar() throws Exception {
72 assertGlobMatches("foo/**", "foo", "foo/bar", "foo/bar/wiz", "foo/baz", "foo/baz/quip",
73 "foo/baz/quip/wiz", "foo/baz/wiz", "foo/bar/wiz/file");
74 }
75
76 @Test
77 public void testIllegalPatterns() throws Exception {
78 for (String prefix : Lists.newArrayList("", "*/", "**/", "ba/")) {
79 String suffix = ("/" + prefix).substring(0, prefix.length());
80 for (String pattern : Lists.newArrayList("**fo", "fo**", "**fo**", "fo**fo", "fo**fo**fo")) {
81 assertIllegalWildcard(prefix + pattern);
82 assertIllegalWildcard(pattern + suffix);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010083 }
84 }
85 }
86
87 @Test
88 public void testDoubleStarPatternWithNamedChild() throws Exception {
89 assertGlobMatches("**/bar", "foo/bar");
90 }
91
92 @Test
93 public void testDoubleStarPatternWithChildGlob() throws Exception {
94 assertGlobMatches("**/ba*",
95 "foo/bar", "foo/baz", "food/baz", "fool/baz");
96 }
97
98 @Test
99 public void testDoubleStarAsChildGlob() throws Exception {
100 assertGlobMatches("foo/**/wiz", "foo/bar/wiz", "foo/baz/quip/wiz", "foo/baz/wiz");
101 }
102
103 @Test
104 public void testDoubleStarUnderNonexistentDirectory() throws Exception {
105 assertGlobMatches("not-there/**" /* => nothing */);
106 }
107
108 @Test
109 public void testDoubleStarGlobWithNonExistentBase() throws Exception {
110 Collection<Path> globResult = UnixGlob.forPath(fileSystem.getPath("/does/not/exist"))
111 .addPattern("**")
112 .globInterruptible();
Ulf Adams795895a2015-03-06 15:58:35 +0000113 assertThat(globResult).isEmpty();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100114 }
115
116 @Test
117 public void testDoubleStarUnderFile() throws Exception {
118 assertGlobMatches("foo/bar/wiz/file/**" /* => nothing */);
119 }
120
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100121 private void assertGlobMatches(String pattern, String... expecteds)
122 throws Exception {
Carmi Grushkofd8acab2015-11-10 17:19:13 +0000123 assertThat(
Nathan Harmata7853e042016-06-06 17:45:48 +0000124 new UnixGlob.Builder(tmpPath)
125 .addPatterns(pattern)
126 .globInterruptible())
127 .containsExactlyElementsIn(resolvePaths(expecteds));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100128 }
129
130 private Set<Path> resolvePaths(String... relativePaths) {
131 Set<Path> expectedFiles = new HashSet<>();
132 for (String expected : relativePaths) {
133 Path file = expected.equals(".")
134 ? tmpPath
135 : tmpPath.getRelative(expected);
136 expectedFiles.add(file);
137 }
138 return expectedFiles;
139 }
140
Nathan Harmata2410ef42016-06-06 18:41:48 +0000141 @Test
142 public void testRecursiveGlobsAreOptimized() throws Exception {
143 long numGlobTasks = new UnixGlob.Builder(tmpPath)
144 .addPattern("**")
145 .setExcludeDirectories(false)
146 .globInterruptibleAndReturnNumGlobTasksForTesting();
147
148 // The old glob implementation used to use 41 total glob tasks.
149 // Yes, checking for an exact value here is super brittle, but it lets us catch performance
150 // regressions. In other words, if you're a developer reading this comment because this test
151 // case is failing, you should be very sure you know what you're doing before you change the
152 // expectation of the test.
153 assertThat(numGlobTasks).isEqualTo(28);
154 }
155
Nathan Harmata7853e042016-06-06 17:45:48 +0000156 private void assertIllegalWildcard(String pattern)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100157 throws Exception {
158 try {
159 new UnixGlob.Builder(tmpPath)
160 .addPattern(pattern)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100161 .globInterruptible();
162 fail();
163 } catch (IllegalArgumentException e) {
Googler2fa3ccf2015-11-10 14:30:39 +0000164 assertThat(e.getMessage()).containsMatch("recursive wildcard must be its own segment");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100165 }
166 }
167
168}