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  }