github.com/xaverkapeller/go-gitignore@v0.0.0-20201129201858-74ef740b8b77/parser_test.go (about)

     1  package gitignore_test
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/denormal/go-gitignore"
     8  )
     9  
    10  type parsetest struct {
    11  	good     int
    12  	bad      int
    13  	position []gitignore.Position
    14  	failures []gitignore.Error
    15  	errors   func(gitignore.Error) bool
    16  } // parsetest{}
    17  
    18  // TestParser tests the behaviour of gitignore.Parser
    19  func TestParser(t *testing.T) {
    20  	_test := &parsetest{good: _GITPATTERNS, bad: _GITBADPATTERNS}
    21  	_test.position = make([]gitignore.Position, 0)
    22  
    23  	// record the position of encountered errors
    24  	_test.errors = func(e gitignore.Error) bool {
    25  		_test.position = append(_test.position, e.Position())
    26  		return true
    27  	}
    28  
    29  	// run this parser test
    30  	parse(t, _test)
    31  } // TestParser()
    32  
    33  // TestParserError tests the behaviour of the gitignore.Parser with an error
    34  // handler that returns false on receiving an error
    35  func TestParserError(t *testing.T) {
    36  	_test := &parsetest{good: _GITPATTERNSFALSE, bad: _GITBADPATTERNSFALSE}
    37  	_test.position = make([]gitignore.Position, 0)
    38  
    39  	// record the position of encountered errors
    40  	//		- return false to stop parsing
    41  	_test.errors = func(e gitignore.Error) bool {
    42  		_test.position = append(_test.position, e.Position())
    43  		return false
    44  	}
    45  
    46  	// run this parser test
    47  	parse(t, _test)
    48  } // TestParserError()
    49  
    50  func TestParserInvalid(t *testing.T) {
    51  	_test := &parsetest{good: _GITINVALIDPATTERNS, bad: _GITINVALIDERRORS}
    52  	_test.position = make([]gitignore.Position, 0)
    53  
    54  	// record the position of encountered errors
    55  	_test.errors = func(e gitignore.Error) bool {
    56  		_test.position = append(_test.position, e.Position())
    57  		_test.failures = append(_test.failures, e)
    58  		return true
    59  	}
    60  
    61  	// run this parser test
    62  	invalidparse(t, _test)
    63  } // TestParserInvalid()
    64  
    65  func TestParserInvalidFalse(t *testing.T) {
    66  	_test := &parsetest{
    67  		good: _GITINVALIDPATTERNSFALSE,
    68  		bad:  _GITINVALIDERRORSFALSE,
    69  	}
    70  	_test.position = make([]gitignore.Position, 0)
    71  
    72  	// record the position of encountered errors
    73  	_test.errors = func(e gitignore.Error) bool {
    74  		_test.position = append(_test.position, e.Position())
    75  		_test.failures = append(_test.failures, e)
    76  		return false
    77  	}
    78  
    79  	// run this parser test
    80  	invalidparse(t, _test)
    81  } // TestParserInvalidFalse()
    82  
    83  func parse(t *testing.T, test *parsetest) {
    84  	// create a temporary .gitignore
    85  	_buffer, _err := buffer(_GITIGNORE)
    86  	if _err != nil {
    87  		t.Fatalf("unable to create temporary .gitignore: %s", _err.Error())
    88  	}
    89  
    90  	// ensure we have a non-nil Parser instance
    91  	_parser := gitignore.NewParser(_buffer, test.errors)
    92  	if _parser == nil {
    93  		t.Error("expected non-nil Parser instance; nil found")
    94  	}
    95  
    96  	// before we parse, what position do we have?
    97  	_position := _parser.Position()
    98  	if !coincident(_position, _BEGINNING) {
    99  		t.Errorf(
   100  			"beginning position mismatch; expected %s, got %s",
   101  			pos(_BEGINNING), pos(_position),
   102  		)
   103  	}
   104  
   105  	// attempt to parse the .gitignore
   106  	_patterns := _parser.Parse()
   107  
   108  	// ensure we encountered the expected bad patterns
   109  	if len(test.position) != test.bad {
   110  		t.Errorf(
   111  			"parse error mismatch; expected %d errors, got %d",
   112  			test.bad, len(test.position),
   113  		)
   114  	} else {
   115  		// ensure the bad pattern positions are correct
   116  		for _i := 0; _i < test.bad; _i++ {
   117  			_got := test.position[_i]
   118  			_expected := _GITBADPOSITION[_i]
   119  
   120  			if !coincident(_got, _expected) {
   121  				t.Errorf(
   122  					"bad pattern position mismatch; expected %q, got %q",
   123  					pos(_expected), pos(_got),
   124  				)
   125  			}
   126  		}
   127  	}
   128  
   129  	// ensure we encountered the right number of good patterns
   130  	if len(_patterns) != test.good {
   131  		t.Errorf(
   132  			"parse pattern mismatch; expected %d patterns, got %d",
   133  			test.good, len(_patterns),
   134  		)
   135  	} else {
   136  		// ensure the good pattern positions are correct
   137  		for _i := 0; _i < len(_patterns); _i++ {
   138  			_got := _patterns[_i].Position()
   139  			_expected := _GITPOSITION[_i]
   140  
   141  			if !coincident(_got, _expected) {
   142  				t.Errorf(
   143  					"pattern position mismatch; expected %q, got %q",
   144  					pos(_expected), pos(_got),
   145  				)
   146  			}
   147  		}
   148  
   149  		// ensure the retrieved patterns are correct
   150  		//		- we check the string form of the pattern against the respective
   151  		//	      lines from the .gitignore
   152  		//		- we must special-case patterns that end in whitespace that
   153  		//		  can be ignored (i.e. it's not escaped)
   154  		_lines := strings.Split(_GITIGNORE, "\n")
   155  		for _i := 0; _i < len(_patterns); _i++ {
   156  			_pattern := _patterns[_i]
   157  			_got := _pattern.String()
   158  			_line := _pattern.Position().Line
   159  			_expected := _lines[_line-1]
   160  
   161  			if _got != _expected {
   162  				// if the two strings aren't the same, then check to see if
   163  				// the difference is trailing whitespace
   164  				//		- the expected string may have whitespace, while the
   165  				//		  pattern string does not
   166  				//		- patterns have their trailing whitespace removed, so
   167  				//	    - we perform this check here, since it's possible for
   168  				//		  a pattern to end in a whitespace character (e.g. '\ ')
   169  				//		  and we don't want to be too heavy handed with our
   170  				//		  removal of whitespace
   171  				//		- only do this check for non-comments
   172  				if !strings.HasPrefix(_expected, "#") {
   173  					_new := strings.TrimRight(_expected, " \t")
   174  					if _new == _got {
   175  						continue
   176  					}
   177  				}
   178  				t.Errorf(
   179  					"pattern mismatch; expected %q, got %q at %s",
   180  					_expected, _got, pos(_pattern.Position()),
   181  				)
   182  			}
   183  		}
   184  	}
   185  } // parse()
   186  
   187  func invalidparse(t *testing.T, test *parsetest) {
   188  	_buffer, _err := buffer(_GITINVALID)
   189  	if _err != nil {
   190  		t.Fatalf("unable to create temporary .gitignore: %s", _err.Error())
   191  	}
   192  
   193  	// create the parser instance
   194  	_parser := gitignore.NewParser(_buffer, test.errors)
   195  	if _parser == nil {
   196  		t.Error("expected non-nil Parser instance; nil found")
   197  	}
   198  
   199  	// attempt to parse the .gitignore
   200  	_patterns := _parser.Parse()
   201  
   202  	// ensure we have the correct number of errors encountered
   203  	if len(test.failures) != test.bad {
   204  		t.Fatalf(
   205  			"unexpected invalid parse errors; expected %d, got %d",
   206  			test.bad, len(test.failures),
   207  		)
   208  	} else {
   209  		for _i := 0; _i < test.bad; _i++ {
   210  			_expected := _GITINVALIDERROR[_i]
   211  			_got := test.failures[_i]
   212  
   213  			// is this error the same as expected?
   214  			//			if !_got.Is(_expected) {
   215  			if _got.Underlying() != _expected {
   216  				t.Fatalf(
   217  					"unexpected invalid parse error; expected %q, got %q",
   218  					_expected.Error(), _got.Error(),
   219  				)
   220  			}
   221  		}
   222  	}
   223  
   224  	// ensure we have the correct number of patterns
   225  	if len(_patterns) != test.good {
   226  		t.Fatalf(
   227  			"unexpected invalid parse patterns; expected %d, got %d",
   228  			test.good, len(_patterns),
   229  		)
   230  	} else {
   231  		for _i := 0; _i < test.good; _i++ {
   232  			_expected := _GITINVALIDPATTERN[_i]
   233  			_got := _patterns[_i]
   234  
   235  			// is this pattern the same as expected?
   236  			if _got.String() != _expected {
   237  				t.Fatalf(
   238  					"unexpected invalid parse pattern; expected %q, got %q",
   239  					_expected, _got,
   240  				)
   241  			}
   242  		}
   243  	}
   244  } // invalidparse()