github.com/ianlewis/go-gitignore@v0.1.1-0.20231110021210-4a0f15cbd56f/match_test.go (about) 1 // Copyright 2016 Denormal Limited 2 // Copyright 2023 Google LLC 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 package gitignore_test 17 18 import ( 19 "os" 20 "path/filepath" 21 "testing" 22 23 "github.com/ianlewis/go-gitignore" 24 ) 25 26 func TestMatch(t *testing.T) { 27 // we need to populate a directory with the match test files 28 // - this is to permit GitIgnore.Match() to correctly resolve 29 // absolute path names 30 _dir, _ignore := directory(t) 31 defer os.RemoveAll(_dir) 32 33 // perform the path matching 34 // - first we test absolute paths 35 _cb := func(path string, isdir bool) gitignore.Match { 36 _path := filepath.Join(_dir, path) 37 return _ignore.Match(_path) 38 } 39 for _, _test := range _GITMATCHES { 40 do(t, _cb, _test) 41 } 42 43 // now, attempt relative path matching 44 // - to do this, we need to change the working directory 45 _cwd, _err := os.Getwd() 46 if _err != nil { 47 t.Fatalf("unable to retrieve working directory: %s", _err.Error()) 48 } 49 _err = os.Chdir(_dir) 50 if _err != nil { 51 t.Fatalf("unable to chdir into temporary directory: %s", _err.Error()) 52 } 53 defer os.Chdir(_cwd) 54 55 // perform the relative path tests 56 _cb = func(path string, isdir bool) gitignore.Match { 57 return _ignore.Match(path) 58 } 59 for _, _test := range _GITMATCHES { 60 do(t, _cb, _test) 61 } 62 63 // perform absolute path tests with paths not under the same root 64 // directory as the GitIgnore we are testing 65 _new, _ := directory(t) 66 defer os.RemoveAll(_new) 67 68 for _, _test := range _GITMATCHES { 69 _path := filepath.Join(_new, _test.Local()) 70 _match := _ignore.Match(_path) 71 if _match != nil { 72 t.Fatalf("unexpected match; expected nil, got %v", _match) 73 } 74 } 75 76 // ensure Match() behaves as expected if the absolute path cannot 77 // be determined 78 // - we do this by choosing as our working directory a path 79 // that this process does not have permission to 80 _dir, _err = dir(nil) 81 if _err != nil { 82 t.Fatalf("unable to create temporary directory: %s", _err.Error()) 83 } 84 defer os.RemoveAll(_dir) 85 86 _err = os.Chdir(_dir) 87 if _err != nil { 88 t.Fatalf("unable to chdir into temporary directory: %s", _err.Error()) 89 } 90 defer os.Chdir(_cwd) 91 92 // remove permission from the temporary directory 93 _err = os.Chmod(_dir, 0) 94 if _err != nil { 95 t.Fatalf( 96 "unable to modify temporary directory permissions: %s: %s", 97 _dir, _err.Error(), 98 ) 99 } 100 101 // now perform the match tests and ensure an error is returned 102 for _, _test := range _GITMATCHES { 103 _match := _ignore.Match(_test.Local()) 104 if _match != nil { 105 t.Fatalf("unexpected match; expected nil, got %v", _match) 106 } 107 } 108 } // TestMatch() 109 110 func TestIgnore(t *testing.T) { 111 // we need to populate a directory with the match test files 112 // - this is to permit GitIgnore.Ignore() to correctly resolve 113 // absolute path names 114 _dir, _ignore := directory(t) 115 defer os.RemoveAll(_dir) 116 117 // perform the path matching 118 // - first we test absolute paths 119 for _, _test := range _GITMATCHES { 120 _path := filepath.Join(_dir, _test.Local()) 121 _rtn := _ignore.Ignore(_path) 122 if _rtn != _test.Ignore { 123 t.Errorf( 124 "ignore mismatch for %q; expected %v, got %v", 125 _path, _test.Ignore, _rtn, 126 ) 127 } 128 } 129 130 // now, attempt relative path matching 131 // - to do this, we need to change the working directory 132 _cwd, _err := os.Getwd() 133 if _err != nil { 134 t.Fatalf("unable to retrieve working directory: %s", _err.Error()) 135 } 136 _err = os.Chdir(_dir) 137 if _err != nil { 138 t.Fatalf("unable to chdir into temporary directory: %s", _err.Error()) 139 } 140 defer os.Chdir(_cwd) 141 142 // perform the relative path tests 143 for _, _test := range _GITMATCHES { 144 _rtn := _ignore.Ignore(_test.Local()) 145 if _rtn != _test.Ignore { 146 t.Errorf( 147 "ignore mismatch for %q; expected %v, got %v", 148 _test.Path, _test.Ignore, _rtn, 149 ) 150 } 151 } 152 153 // perform absolute path tests with paths not under the same root 154 // directory as the GitIgnore we are testing 155 _new, _ := directory(t) 156 defer os.RemoveAll(_new) 157 158 for _, _test := range _GITMATCHES { 159 _path := filepath.Join(_new, _test.Local()) 160 _ignore := _ignore.Ignore(_path) 161 if _ignore { 162 t.Fatalf("unexpected ignore for %q", _path) 163 } 164 } 165 } // TestIgnore() 166 167 func TestInclude(t *testing.T) { 168 // we need to populate a directory with the match test files 169 // - this is to permit GitIgnore.Include() to correctly resolve 170 // absolute path names 171 _dir, _ignore := directory(t) 172 defer os.RemoveAll(_dir) 173 174 // perform the path matching 175 // - first we test absolute paths 176 for _, _test := range _GITMATCHES { 177 _path := filepath.Join(_dir, _test.Local()) 178 _rtn := _ignore.Include(_path) 179 if _rtn == _test.Ignore { 180 t.Errorf( 181 "include mismatch for %q; expected %v, got %v", 182 _path, !_test.Ignore, _rtn, 183 ) 184 } 185 } 186 187 // now, attempt relative path matching 188 // - to do this, we need to change the working directory 189 _cwd, _err := os.Getwd() 190 if _err != nil { 191 t.Fatalf("unable to retrieve working directory: %s", _err.Error()) 192 } 193 _err = os.Chdir(_dir) 194 if _err != nil { 195 t.Fatalf("unable to chdir into temporary directory: %s", _err.Error()) 196 } 197 defer os.Chdir(_cwd) 198 199 // perform the relative path tests 200 for _, _test := range _GITMATCHES { 201 _rtn := _ignore.Include(_test.Local()) 202 if _rtn == _test.Ignore { 203 t.Errorf( 204 "include mismatch for %q; expected %v, got %v", 205 _test.Path, !_test.Ignore, _rtn, 206 ) 207 } 208 } 209 210 // perform absolute path tests with paths not under the same root 211 // directory as the GitIgnore we are testing 212 _new, _ := directory(t) 213 defer os.RemoveAll(_new) 214 215 for _, _test := range _GITMATCHES { 216 _path := filepath.Join(_new, _test.Local()) 217 _include := _ignore.Include(_path) 218 if !_include { 219 t.Fatalf("unexpected include for %q", _path) 220 } 221 } 222 } // TestInclude() 223 224 func TestMatchRelative(t *testing.T) { 225 // create a temporary .gitignore 226 _buffer, _err := buffer(_GITMATCH) 227 if _err != nil { 228 t.Fatalf("unable to create temporary .gitignore: %s", _err.Error()) 229 } 230 231 // ensure we can run New() 232 // - ensure we encounter no errors 233 _position := []gitignore.Position{} 234 _error := func(e gitignore.Error) bool { 235 _position = append(_position, e.Position()) 236 return true 237 } 238 239 // ensure we have a non-nil GitIgnore instance 240 _ignore := gitignore.New(_buffer, _GITBASE, _error) 241 if _ignore == nil { 242 t.Error("expected non-nil GitIgnore instance; nil found") 243 } 244 245 // ensure we encountered the right number of errors 246 if len(_position) != _GITBADMATCHPATTERNS { 247 t.Errorf( 248 "match error mismatch; expected %d errors, got %d", 249 _GITBADMATCHPATTERNS, len(_position), 250 ) 251 } 252 253 // perform the relative path matching 254 _cb := func(path string, isdir bool) gitignore.Match { 255 return _ignore.Relative(path, isdir) 256 } 257 for _, _test := range _GITMATCHES { 258 do(t, _cb, _test) 259 } 260 } // TestMatchRelative() 261 262 func do(t *testing.T, cb func(string, bool) gitignore.Match, m match) { 263 // attempt to match this path 264 _match := cb(m.Local(), m.IsDir()) 265 if _match == nil { 266 // we have no match, is this expected? 267 // - a test that matches will list the expected pattern 268 if m.Pattern != "" { 269 t.Errorf( 270 "failed match; expected match for %q by %q", 271 m.Path, m.Pattern, 272 ) 273 return 274 } 275 276 // since we have no match, ensure this path is not ignored 277 if m.Ignore { 278 t.Errorf( 279 "failed ignore; no match for %q but expected to be ignored", 280 m.Path, 281 ) 282 } 283 } else { 284 // we have a match, is this expected? 285 // - a test that matches will list the expected pattern 286 if m.Pattern == "" { 287 t.Errorf( 288 "unexpected match by %q; expected no match for %q", 289 _match, m.Path, 290 ) 291 return 292 } else if m.Pattern != _match.String() { 293 t.Errorf( 294 "mismatch for %q; expected match pattern %q, got %q", 295 m.Path, m.Pattern, _match.String(), 296 ) 297 return 298 } 299 300 // since we have a match, are we expected to ignore this file? 301 if m.Ignore != _match.Ignore() { 302 t.Errorf( 303 "ignore mismatch; expected %v for %q Ignore(), "+ 304 "got %v from pattern %q", 305 m.Ignore, m.Path, _match.Ignore(), _match, 306 ) 307 } 308 } 309 } // do() 310 311 func directory(t *testing.T) (string, gitignore.GitIgnore) { 312 // we need to populate a directory with the match test files 313 // - this is to permit GitIgnore.Match() to correctly resolve 314 // absolute path names 315 // - populate the directory by passing a map of file names and their 316 // contents 317 // - the content is not important, it just can't be empty 318 // - use this mechanism to also populate the .gitignore file 319 _map := map[string]string{gitignore.File: _GITMATCH} 320 for _, _test := range _GITMATCHES { 321 _map[_test.Path] = " " // this is the file contents 322 } 323 324 // create the temporary directory 325 _dir, _err := dir(_map) 326 if _err != nil { 327 t.Fatalf("unable to create temporary .gitignore: %s", _err.Error()) 328 } 329 330 // ensure we can run New() 331 // - ensure we encounter no errors 332 _position := []gitignore.Position{} 333 _error := func(e gitignore.Error) bool { 334 _position = append(_position, e.Position()) 335 return true 336 } 337 338 // ensure we have a non-nil GitIgnore instance 339 _file := filepath.Join(_dir, gitignore.File) 340 _ignore := gitignore.NewWithErrors(_file, _error) 341 if _ignore == nil { 342 t.Fatalf("expected non-nil GitIgnore instance; nil found") 343 } 344 345 // ensure we encountered the right number of errors 346 if len(_position) != _GITBADMATCHPATTERNS { 347 t.Errorf( 348 "match error mismatch; expected %d errors, got %d", 349 _GITBADMATCHPATTERNS, len(_position), 350 ) 351 } 352 353 // return the directory name and the GitIgnore instance 354 return _dir, _ignore 355 } // directory()