github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/strutil/matchcounter_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package strutil_test 21 22 import ( 23 "regexp" 24 25 "gopkg.in/check.v1" 26 27 "github.com/snapcore/snapd/strutil" 28 ) 29 30 type mcSuite struct{} 31 32 var _ = check.Suite(&mcSuite{}) 33 34 const out = ` 35 36 Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols, skipping 37 38 Write on output file failed because No space left on device 39 40 Hello I am a happy line that does not mention failure. 41 42 writer: failed to write data block 0 43 44 Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols.bin, skipping 45 46 Write on output file failed because No space left on device 47 48 writer: failed to write data block 0 49 50 Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdso32.so, skipping 51 52 Write on output file failed because No space left on device 53 54 La la la. 55 56 writer: failed to write data block 0 57 58 Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdso64.so, skipping 59 60 Write on output file failed because No space left on device 61 62 writer: failed to write data block 0 63 64 Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdsox32.so, skipping 65 66 Write on output file failed because No space left on device 67 68 writer: failed to write data block 0 69 70 Failed to write /tmp/1/snap/manifest.yaml, skipping 71 72 🦄🌈💩 73 74 Write on output file failed because No space left on device 75 76 writer: failed to write data block 0 77 78 Failed to write /tmp/1/snap/snapcraft.yaml, skipping 79 ` 80 81 var thisRegexp = regexp.MustCompile("(?m).*[Ff]ailed.*") 82 var nilRegexpEquiv = regexp.MustCompile("(?m).+") 83 84 func (mcSuite) TestMatchCounterFull(c *check.C) { 85 // check a single write 86 expected := thisRegexp.FindAllString(out, 3) 87 w := &strutil.MatchCounter{Regexp: thisRegexp, N: 3} 88 _, err := w.Write([]byte(out)) 89 c.Assert(err, check.IsNil) 90 matches, count := w.Matches() 91 c.Check(count, check.Equals, 19) 92 c.Assert(matches, check.DeepEquals, expected) 93 94 expectedLast := []string{ 95 "Write on output file failed because No space left on device", 96 "writer: failed to write data block 0", 97 "Failed to write /tmp/1/snap/snapcraft.yaml, skipping", 98 } 99 wLast := &strutil.MatchCounter{Regexp: thisRegexp, N: 3, LastN: true} 100 _, err = wLast.Write([]byte(out)) 101 c.Assert(err, check.IsNil) 102 matches, count = wLast.Matches() 103 c.Check(count, check.Equals, 19) 104 c.Assert(matches, check.DeepEquals, expectedLast) 105 } 106 107 func (mcSuite) TestMatchCounterPartials(c *check.C) { 108 // now we know the whole thing matches expected, we check partials 109 buf := []byte(out) 110 expected := []string{ 111 "Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols, skipping", 112 "Write on output file failed because No space left on device", 113 "writer: failed to write data block 0", 114 } 115 expectedLast := []string{ 116 "Write on output file failed because No space left on device", 117 "writer: failed to write data block 0", 118 "Failed to write /tmp/1/snap/snapcraft.yaml, skipping", 119 } 120 121 for _, keepLast := range []bool{false, true} { 122 for step := 1; step < 100; step++ { 123 w := &strutil.MatchCounter{Regexp: thisRegexp, N: 3, LastN: keepLast} 124 var i int 125 for i = 0; i+step < len(buf); i += step { 126 _, err := w.Write(buf[i : i+step]) 127 c.Assert(err, check.IsNil, check.Commentf("step:%d i:%d", step, i)) 128 } 129 _, err := w.Write(buf[i:]) 130 c.Assert(err, check.IsNil, check.Commentf("step:%d tail", step)) 131 matches, count := w.Matches() 132 c.Check(count, check.Equals, 19, check.Commentf("step:%d", step)) 133 if !keepLast { 134 c.Check(matches, check.DeepEquals, expected, check.Commentf("step:%d", step)) 135 } else { 136 c.Check(matches, check.DeepEquals, expectedLast, check.Commentf("step:%d", step)) 137 } 138 } 139 } 140 } 141 142 func (mcSuite) TestMatchCounterPartialsReusingBuffer(c *check.C) { 143 // now we know the whole thing matches expected, we check partials 144 buf := []byte(out) 145 expected := []string{ 146 "Failed to write /tmp/1/modules/4.4.0-112-generic/modules.symbols, skipping", 147 "Write on output file failed because No space left on device", 148 "writer: failed to write data block 0", 149 } 150 151 for step := 1; step < 100; step++ { 152 wbuf := make([]byte, step) 153 w := &strutil.MatchCounter{Regexp: thisRegexp, N: 3} 154 var i int 155 for i = 0; i+step < len(buf); i += step { 156 copy(wbuf, buf[i:]) 157 _, err := w.Write(wbuf) 158 c.Assert(err, check.IsNil, check.Commentf("step:%d i:%d", step, i)) 159 } 160 wbuf = wbuf[:len(buf[i:])] 161 copy(wbuf, buf[i:]) 162 _, err := w.Write(wbuf) 163 c.Assert(err, check.IsNil, check.Commentf("step:%d tail", step)) 164 matches, count := w.Matches() 165 c.Assert(count, check.Equals, 19, check.Commentf("step:%d", step)) 166 c.Assert(matches, check.DeepEquals, expected, check.Commentf("step:%d", step)) 167 } 168 } 169 170 func (mcSuite) TestMatchCounterZero(c *check.C) { 171 w := &strutil.MatchCounter{Regexp: thisRegexp, N: 0} 172 _, err := w.Write([]byte(out)) 173 c.Assert(err, check.IsNil) 174 matches, count := w.Matches() 175 c.Check(count, check.Equals, 19) 176 c.Assert(matches, check.HasLen, 0) 177 178 wLast := &strutil.MatchCounter{Regexp: thisRegexp, N: 0, LastN: true} 179 _, err = wLast.Write([]byte(out)) 180 c.Assert(err, check.IsNil) 181 matches, count = w.Matches() 182 c.Check(count, check.Equals, 19) 183 c.Assert(matches, check.HasLen, 0) 184 } 185 186 func (mcSuite) TestMatchCounterNegative(c *check.C) { 187 expected := thisRegexp.FindAllString(out, -1) 188 189 w := &strutil.MatchCounter{Regexp: thisRegexp, N: -1} 190 _, err := w.Write([]byte(out)) 191 c.Assert(err, check.IsNil) 192 matches, count := w.Matches() 193 c.Check(count, check.Equals, 19) 194 c.Check(count, check.Equals, len(matches)) 195 c.Assert(matches, check.DeepEquals, expected) 196 197 // always keep all lines 198 wLast := &strutil.MatchCounter{Regexp: thisRegexp, N: -1, LastN: true} 199 _, err = wLast.Write([]byte(out)) 200 c.Assert(err, check.IsNil) 201 matches, count = w.Matches() 202 c.Check(count, check.Equals, 19) 203 c.Check(count, check.Equals, len(matches)) 204 c.Assert(matches, check.DeepEquals, expected) 205 } 206 207 func (mcSuite) TestMatchCounterNilRegexpFull(c *check.C) { 208 expected := nilRegexpEquiv.FindAllString(out, -1) 209 w := &strutil.MatchCounter{N: -1} 210 _, err := w.Write([]byte(out)) 211 c.Assert(err, check.IsNil) 212 matches, count := w.Matches() 213 c.Check(count, check.Equals, len(matches)) 214 c.Check(len(matches), check.Equals, len(expected)) 215 c.Assert(matches, check.DeepEquals, expected) 216 } 217 218 func (mcSuite) TestMatchCounterNilRegexpLimited(c *check.C) { 219 expected := nilRegexpEquiv.FindAllString(out, 10) 220 w := &strutil.MatchCounter{N: 10} 221 _, err := w.Write([]byte(out)) 222 c.Assert(err, check.IsNil) 223 matches, count := w.Matches() 224 c.Check(count, check.Equals, 22) 225 c.Check(len(matches), check.Equals, len(expected)) 226 c.Assert(matches, check.DeepEquals, expected) 227 228 expectedLast := []string{ 229 // "writer: failed to write data block 0", 230 // "Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdso64.so, skipping", 231 "Write on output file failed because No space left on device", 232 "writer: failed to write data block 0", 233 "Failed to write /tmp/1/modules/4.4.0-112-generic/vdso/vdsox32.so, skipping", 234 "Write on output file failed because No space left on device", 235 "writer: failed to write data block 0", 236 "Failed to write /tmp/1/snap/manifest.yaml, skipping", 237 "🦄🌈💩", 238 "Write on output file failed because No space left on device", 239 "writer: failed to write data block 0", 240 "Failed to write /tmp/1/snap/snapcraft.yaml, skipping", 241 } 242 wLast := &strutil.MatchCounter{N: 10, LastN: true} 243 _, err = wLast.Write([]byte(out)) 244 c.Assert(err, check.IsNil) 245 matches, count = wLast.Matches() 246 c.Check(count, check.Equals, 22) 247 c.Check(len(matches), check.Equals, len(expectedLast)) 248 c.Assert(matches, check.DeepEquals, expectedLast) 249 } 250 251 func (mcSuite) TestMatchCounterNilRegexpPartials(c *check.C) { 252 expected := nilRegexpEquiv.FindAllString(out, 3) 253 254 buf := []byte(out) 255 for step := 1; step < 100; step++ { 256 w := &strutil.MatchCounter{N: 3} 257 var i int 258 for i = 0; i+step < len(buf); i += step { 259 _, err := w.Write(buf[i : i+step]) 260 c.Assert(err, check.IsNil, check.Commentf("step:%d i:%d", step, i)) 261 } 262 _, err := w.Write(buf[i:]) 263 c.Assert(err, check.IsNil, check.Commentf("step:%d tail", step)) 264 matches, count := w.Matches() 265 c.Check(count, check.Equals, 22, check.Commentf("step:%d", step)) 266 c.Check(matches, check.DeepEquals, expected, check.Commentf("step:%d", step)) 267 } 268 }