github.com/juju/charm/v11@v11.2.0/jujuignore_test.go (about) 1 // Copyright 2019 Canonical Ltd. 2 // Licensed under the LGPLv3, see LICENCE file for details. 3 4 package charm 5 6 import ( 7 "strings" 8 9 gc "gopkg.in/check.v1" 10 ) 11 12 type JujuIgnoreSuite struct{} 13 14 var _ = gc.Suite(&JujuIgnoreSuite{}) 15 16 func (s *JujuIgnoreSuite) TestBuildRules(c *gc.C) { 17 type test struct { 18 path string 19 isDir bool 20 expMatch bool 21 } 22 23 specs := []struct { 24 descr string 25 rules string 26 tests []test 27 }{ 28 { 29 descr: `Match a directory named "target" at any depth`, 30 rules: `target/`, 31 tests: []test{ 32 {path: "target", isDir: true, expMatch: true}, 33 {path: "foo/target", isDir: true, expMatch: true}, 34 {path: "foo/1target", isDir: true, expMatch: false}, 35 {path: "foo/target", isDir: false, expMatch: false}, 36 }, 37 }, 38 { 39 descr: `Match a directory OR a file named "target" at any depth`, 40 rules: `target`, 41 tests: []test{ 42 {path: "/target", isDir: true, expMatch: true}, 43 {path: "/foo/target", isDir: true, expMatch: true}, 44 {path: "/foo/1target", isDir: true, expMatch: false}, 45 {path: "/foo/target", isDir: false, expMatch: true}, 46 }, 47 }, 48 { 49 descr: `Match a directory at the root only`, 50 rules: `/target/`, 51 tests: []test{ 52 {path: "/target", isDir: true, expMatch: true}, 53 {path: "/foo/target", isDir: true, expMatch: false}, 54 {path: "/target", isDir: false, expMatch: false}, 55 }, 56 }, 57 { 58 descr: `Match a directory OR file at the root only`, 59 rules: `/target`, 60 tests: []test{ 61 {path: "/target", isDir: true, expMatch: true}, 62 {path: "/foo/target", isDir: true, expMatch: false}, 63 {path: "/target", isDir: false, expMatch: true}, 64 }, 65 }, 66 { 67 descr: `Every file or dir ending with .go recursively`, 68 rules: `*.go`, 69 tests: []test{ 70 {path: "/target.go", isDir: true, expMatch: true}, 71 {path: "/target.go", isDir: false, expMatch: true}, 72 {path: "/foo/target.go", isDir: true, expMatch: true}, 73 {path: "/foo/target.go", isDir: false, expMatch: true}, 74 {path: "/target.goT", isDir: true, expMatch: false}, 75 {path: "/target.goT", isDir: false, expMatch: false}, 76 }, 77 }, 78 { 79 descr: `every file or dir named "#comment"`, 80 rules: ` 81 # NOTE: leading hash must be escaped so as not to treat line as a comment 82 \#comment 83 `, 84 tests: []test{ 85 {path: "/#comment", isDir: true, expMatch: true}, 86 {path: "/#comment", isDir: false, expMatch: true}, 87 }, 88 }, 89 { 90 descr: `Every dir called "logs" under "apps"`, 91 rules: `apps/logs/`, 92 tests: []test{ 93 {path: "/apps/logs", isDir: true, expMatch: true}, 94 {path: "/apps/foo/logs", isDir: true, expMatch: false}, 95 }, 96 }, 97 { 98 descr: `Every dir called "logs" two levels under "apps"`, 99 rules: `apps/*/logs/`, 100 tests: []test{ 101 {path: "/apps/foo/logs", isDir: true, expMatch: true}, 102 {path: "/apps/foo/bar/logs", isDir: true, expMatch: false}, 103 {path: "/apps/logs", isDir: true, expMatch: false}, 104 }, 105 }, 106 { 107 descr: `Every dir called "logs" any number of levels under "apps"`, 108 rules: `apps/**/logs/`, 109 tests: []test{ 110 {path: "/apps/foo/logs", isDir: true, expMatch: true}, 111 {path: "/apps/foo/bar/logs", isDir: true, expMatch: true}, 112 {path: "/apps/logs", isDir: true, expMatch: true}, 113 }, 114 }, 115 { 116 descr: `Ignore all under "foo" but not "foo" itself`, 117 rules: `foo/**`, 118 tests: []test{ 119 {path: "/foo", isDir: true, expMatch: false}, 120 {path: "/foo/something", isDir: true, expMatch: true}, 121 {path: "/foo/something.txt", isDir: false, expMatch: true}, 122 }, 123 }, 124 { 125 descr: `Ignore all under "foo" except README.md`, 126 rules: ` 127 foo/** 128 !foo/README.md 129 `, 130 tests: []test{ 131 {path: "/foo", isDir: true, expMatch: false}, 132 {path: "/foo/something", isDir: true, expMatch: true}, 133 {path: "/foo/something.txt", isDir: false, expMatch: true}, 134 {path: "/foo/README.md", isDir: false, expMatch: false}, 135 }, 136 }, 137 { 138 descr: `Multiple double-star separators`, 139 rules: `foo/**/bar/**/baz`, 140 tests: []test{ 141 {path: "/foo/1/2/bar/baz", isDir: true, expMatch: true}, 142 {path: "/foo/1/2/bar/1/2/baz", isDir: true, expMatch: true}, 143 {path: "/foo/bar/1/baz", isDir: true, expMatch: true}, 144 {path: "/foo/1/bar/baz", isDir: true, expMatch: true}, 145 {path: "/foo/bar/baz", isDir: true, expMatch: true}, 146 }, 147 }, 148 } 149 150 for specIndex, spec := range specs { 151 c.Logf("[spec %d] %s", specIndex, spec.descr) 152 153 rs, err := newIgnoreRuleset(strings.NewReader(spec.rules)) 154 if err != nil { 155 c.Assert(err, gc.IsNil) 156 continue 157 } 158 159 for testIndex, test := range spec.tests { 160 c.Logf(" [test %d] match against path %q", testIndex, test.path) 161 c.Assert(rs.Match(test.path, test.isDir), gc.DeepEquals, test.expMatch) 162 } 163 } 164 } 165 166 func (s *JujuIgnoreSuite) TestGenIgnorePatternPermutations(c *gc.C) { 167 specs := []struct { 168 in string 169 exp []string 170 }{ 171 { 172 in: "foo/bar", 173 exp: []string{"foo/bar"}, 174 }, 175 { 176 in: "foo/**/bar", 177 exp: []string{ 178 "foo/**/bar", 179 "foo/bar", 180 }, 181 }, 182 { 183 in: "foo/**/bar/**/baz", 184 exp: []string{ 185 "foo/**/bar/**/baz", 186 "foo/bar/**/baz", 187 "foo/**/bar/baz", 188 "foo/bar/baz", 189 }, 190 }, 191 } 192 193 for specIndex, spec := range specs { 194 c.Logf(" [spec %d] gen permutations for %q", specIndex, spec.in) 195 got := genIgnorePatternPermutations(spec.in) 196 c.Assert(got, gc.DeepEquals, spec.exp) 197 } 198 } 199 200 func (s *JujuIgnoreSuite) TestUnescapeIgnorePattern(c *gc.C) { 201 specs := []struct { 202 desc string 203 in string 204 exp string 205 }{ 206 { 207 desc: "trailing unescaped spaces should be trimmed", 208 in: `lore\ m\ `, 209 exp: `lore m `, 210 }, 211 { 212 desc: "escaped hashes should be unescaped", 213 in: `\#this-is-not-a-comment`, 214 exp: `#this-is-not-a-comment`, 215 }, 216 { 217 desc: "escaped bangs should be unescaped", 218 in: `\!important`, 219 exp: `!important`, 220 }, 221 } 222 223 for specIndex, spec := range specs { 224 c.Logf("[spec %d] %s", specIndex, spec.desc) 225 c.Assert(unescapeIgnorePattern(spec.in), gc.Equals, spec.exp) 226 } 227 }