github.com/lambdatest/go-gitignore@v0.0.0-20230214141342-7fe15342e580/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()