github.com/boyter/gocodewalker@v1.3.2/go-gitignore/match_test.go (about)

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