gitee.com/mysnapcore/mysnapd@v0.1.0/asserts/internal/grouping_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2020 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 internal_test
    21  
    22  import (
    23  	"encoding/base64"
    24  	"errors"
    25  	"testing"
    26  
    27  	. "gopkg.in/check.v1"
    28  
    29  	"gitee.com/mysnapcore/mysnapd/asserts/internal"
    30  )
    31  
    32  func TestInternal(t *testing.T) { TestingT(t) }
    33  
    34  type groupingsSuite struct{}
    35  
    36  var _ = Suite(&groupingsSuite{})
    37  
    38  func (s *groupingsSuite) TestNewGroupings(c *C) {
    39  	tests := []struct {
    40  		n   int
    41  		err string
    42  	}{
    43  		{-10, `n=-10 groups is outside of valid range \(0, 65536\]`},
    44  		{0, `n=0 groups is outside of valid range \(0, 65536\]`},
    45  		{9, "n=9 groups is not a multiple of 16"},
    46  		{16, ""},
    47  		{255, "n=255 groups is not a multiple of 16"},
    48  		{256, ""},
    49  		{1024, ""},
    50  		{65536, ""},
    51  		{65537, `n=65537 groups is outside of valid range \(0, 65536\]`},
    52  	}
    53  
    54  	for _, t := range tests {
    55  		comm := Commentf("%d", t.n)
    56  		gr, err := internal.NewGroupings(t.n)
    57  		if t.err == "" {
    58  			c.Check(err, IsNil, comm)
    59  			c.Check(gr, NotNil, comm)
    60  			c.Check(gr.N(), Equals, t.n)
    61  		} else {
    62  			c.Check(gr, IsNil, comm)
    63  			c.Check(err, ErrorMatches, t.err, comm)
    64  		}
    65  	}
    66  }
    67  
    68  func (s *groupingsSuite) TestAddToAndContains(c *C) {
    69  	var g internal.Grouping
    70  
    71  	gr, err := internal.NewGroupings(16)
    72  	c.Assert(err, IsNil)
    73  
    74  	err = gr.AddTo(&g, 1)
    75  	c.Assert(err, IsNil)
    76  	err = gr.AddTo(&g, 3)
    77  	c.Assert(err, IsNil)
    78  	err = gr.AddTo(&g, 0)
    79  	c.Assert(err, IsNil)
    80  	err = gr.AddTo(&g, 4)
    81  	c.Assert(err, IsNil)
    82  	err = gr.AddTo(&g, 2)
    83  	c.Assert(err, IsNil)
    84  
    85  	for i := uint16(0); i < 5; i++ {
    86  		c.Check(gr.Contains(&g, i), Equals, true)
    87  	}
    88  
    89  	c.Check(gr.Contains(&g, 5), Equals, false)
    90  }
    91  
    92  func (s *groupingsSuite) TestOutsideRange(c *C) {
    93  	var g internal.Grouping
    94  
    95  	gr, err := internal.NewGroupings(16)
    96  	c.Assert(err, IsNil)
    97  
    98  	// validity
    99  	err = gr.AddTo(&g, 15)
   100  	c.Assert(err, IsNil)
   101  
   102  	err = gr.AddTo(&g, 16)
   103  	c.Check(err, ErrorMatches, "group exceeds admissible maximum: 16 >= 16")
   104  
   105  	err = gr.AddTo(&g, 99)
   106  	c.Check(err, ErrorMatches, "group exceeds admissible maximum: 99 >= 16")
   107  }
   108  
   109  func (s *groupingsSuite) TestSerializeLabel(c *C) {
   110  	var g internal.Grouping
   111  
   112  	gr, err := internal.NewGroupings(128)
   113  	c.Assert(err, IsNil)
   114  
   115  	err = gr.AddTo(&g, 1)
   116  	c.Assert(err, IsNil)
   117  	err = gr.AddTo(&g, 3)
   118  	c.Assert(err, IsNil)
   119  	err = gr.AddTo(&g, 0)
   120  	c.Assert(err, IsNil)
   121  	err = gr.AddTo(&g, 4)
   122  	c.Assert(err, IsNil)
   123  	err = gr.AddTo(&g, 2)
   124  	c.Assert(err, IsNil)
   125  
   126  	l := gr.Serialize(&g)
   127  
   128  	g1, err := gr.Deserialize(l)
   129  	c.Check(err, IsNil)
   130  
   131  	c.Check(g1, DeepEquals, &g)
   132  }
   133  
   134  func (s *groupingsSuite) TestDeserializeLabelErrors(c *C) {
   135  	var g internal.Grouping
   136  
   137  	gr, err := internal.NewGroupings(64)
   138  	c.Assert(err, IsNil)
   139  
   140  	err = gr.AddTo(&g, 0)
   141  	c.Assert(err, IsNil)
   142  	err = gr.AddTo(&g, 1)
   143  	c.Assert(err, IsNil)
   144  	err = gr.AddTo(&g, 2)
   145  	c.Assert(err, IsNil)
   146  	err = gr.AddTo(&g, 3)
   147  	c.Assert(err, IsNil)
   148  	err = gr.AddTo(&g, 4)
   149  	c.Assert(err, IsNil)
   150  
   151  	const errPrefix = "invalid serialized grouping label: "
   152  
   153  	invalidLabels := []struct {
   154  		invalid, errSuffix string
   155  	}{
   156  		// not base64
   157  		{"\x0a\x02\xf4", `illegal base64 data.*`},
   158  		// wrong length
   159  		{base64.RawURLEncoding.EncodeToString([]byte{1}), `not divisible into 16-bits words`},
   160  		// not a known group
   161  		{internal.Serialize([]uint16{5}), `element larger than maximum group`},
   162  		// not in order
   163  		{internal.Serialize([]uint16{0, 2, 1}), `not sorted`},
   164  		// bitset: too many words
   165  		{internal.Serialize([]uint16{0, 0, 0, 0, 0, 0}), `too large`},
   166  		// bitset: larger than maxgroup
   167  		{internal.Serialize([]uint16{6, 0, 0, 0, 0}), `bitset size cannot be possibly larger than maximum group plus 1`},
   168  		// bitset: grouping size is too small
   169  		{internal.Serialize([]uint16{0, 0, 0, 0, 0}), `bitset for too few elements`},
   170  		{internal.Serialize([]uint16{1, 0, 0, 0, 0}), `bitset for too few elements`},
   171  		{internal.Serialize([]uint16{4, 0, 0, 0, 0}), `bitset for too few elements`},
   172  	}
   173  
   174  	for _, il := range invalidLabels {
   175  		_, err := gr.Deserialize(il.invalid)
   176  		c.Check(err, ErrorMatches, errPrefix+il.errSuffix)
   177  	}
   178  }
   179  
   180  func (s *groupingsSuite) TestIter(c *C) {
   181  	var g internal.Grouping
   182  
   183  	gr, err := internal.NewGroupings(128)
   184  	c.Assert(err, IsNil)
   185  
   186  	err = gr.AddTo(&g, 1)
   187  	c.Assert(err, IsNil)
   188  	err = gr.AddTo(&g, 3)
   189  	c.Assert(err, IsNil)
   190  	err = gr.AddTo(&g, 0)
   191  	c.Assert(err, IsNil)
   192  	err = gr.AddTo(&g, 4)
   193  	c.Assert(err, IsNil)
   194  	err = gr.AddTo(&g, 2)
   195  	c.Assert(err, IsNil)
   196  
   197  	elems := []uint16{}
   198  	f := func(group uint16) error {
   199  		elems = append(elems, group)
   200  		return nil
   201  	}
   202  
   203  	err = gr.Iter(&g, f)
   204  	c.Assert(err, IsNil)
   205  	c.Check(elems, DeepEquals, []uint16{0, 1, 2, 3, 4})
   206  }
   207  
   208  func (s *groupingsSuite) TestIterError(c *C) {
   209  	var g internal.Grouping
   210  
   211  	gr, err := internal.NewGroupings(32)
   212  	c.Assert(err, IsNil)
   213  
   214  	err = gr.AddTo(&g, 1)
   215  	c.Assert(err, IsNil)
   216  	err = gr.AddTo(&g, 3)
   217  	c.Assert(err, IsNil)
   218  
   219  	errBoom := errors.New("boom")
   220  	n := 0
   221  	f := func(group uint16) error {
   222  		n++
   223  		return errBoom
   224  	}
   225  
   226  	err = gr.Iter(&g, f)
   227  	c.Check(err, Equals, errBoom)
   228  	c.Check(n, Equals, 1)
   229  }
   230  
   231  func (s *groupingsSuite) TestRepeated(c *C) {
   232  	var g internal.Grouping
   233  
   234  	gr, err := internal.NewGroupings(64)
   235  	c.Assert(err, IsNil)
   236  
   237  	err = gr.AddTo(&g, 1)
   238  	c.Assert(err, IsNil)
   239  	err = gr.AddTo(&g, 0)
   240  	c.Assert(err, IsNil)
   241  	err = gr.AddTo(&g, 2)
   242  	c.Assert(err, IsNil)
   243  
   244  	err = gr.AddTo(&g, 1)
   245  	c.Assert(err, IsNil)
   246  	err = gr.AddTo(&g, 0)
   247  	c.Assert(err, IsNil)
   248  
   249  	elems := []uint16{}
   250  	f := func(group uint16) error {
   251  		elems = append(elems, group)
   252  		return nil
   253  	}
   254  
   255  	err = gr.Iter(&g, f)
   256  	c.Assert(err, IsNil)
   257  	c.Check(elems, DeepEquals, []uint16{0, 1, 2})
   258  }
   259  
   260  func (s *groupingsSuite) TestCopy(c *C) {
   261  	var g internal.Grouping
   262  
   263  	gr, err := internal.NewGroupings(16)
   264  	c.Assert(err, IsNil)
   265  
   266  	err = gr.AddTo(&g, 1)
   267  	c.Assert(err, IsNil)
   268  	err = gr.AddTo(&g, 3)
   269  	c.Assert(err, IsNil)
   270  	err = gr.AddTo(&g, 0)
   271  	c.Assert(err, IsNil)
   272  	err = gr.AddTo(&g, 4)
   273  	c.Assert(err, IsNil)
   274  	err = gr.AddTo(&g, 2)
   275  	c.Assert(err, IsNil)
   276  
   277  	g2 := g.Copy()
   278  	c.Check(g2, DeepEquals, g)
   279  
   280  	err = gr.AddTo(&g2, 7)
   281  	c.Assert(err, IsNil)
   282  
   283  	c.Check(gr.Contains(&g, 7), Equals, false)
   284  	c.Check(gr.Contains(&g2, 7), Equals, true)
   285  
   286  	c.Check(g2, Not(DeepEquals), g)
   287  }
   288  func (s *groupingsSuite) TestBitsetSerializeAndIterSimple(c *C) {
   289  	gr, err := internal.NewGroupings(32)
   290  	c.Assert(err, IsNil)
   291  
   292  	var elems []uint16
   293  	f := func(group uint16) error {
   294  		elems = append(elems, group)
   295  		return nil
   296  	}
   297  
   298  	var g internal.Grouping
   299  	err = gr.AddTo(&g, 1)
   300  	c.Assert(err, IsNil)
   301  	err = gr.AddTo(&g, 5)
   302  	c.Assert(err, IsNil)
   303  	err = gr.AddTo(&g, 17)
   304  	c.Assert(err, IsNil)
   305  	err = gr.AddTo(&g, 24)
   306  	c.Assert(err, IsNil)
   307  
   308  	l := gr.Serialize(&g)
   309  	c.Check(l, DeepEquals,
   310  		internal.Serialize([]uint16{4,
   311  			uint16(1<<1 | 1<<5),
   312  			uint16(1<<(17-16) | 1<<(24-16)),
   313  		}))
   314  
   315  	err = gr.Iter(&g, f)
   316  	c.Assert(err, IsNil)
   317  	c.Check(elems, DeepEquals, []uint16{1, 5, 17, 24})
   318  }
   319  
   320  func (s *groupingsSuite) TestBitSet(c *C) {
   321  	var g internal.Grouping
   322  
   323  	gr, err := internal.NewGroupings(64)
   324  	c.Assert(err, IsNil)
   325  
   326  	for i := uint16(0); i < 64; i++ {
   327  		err := gr.AddTo(&g, i)
   328  		c.Assert(err, IsNil)
   329  		c.Check(gr.Contains(&g, i), Equals, true)
   330  
   331  		l := gr.Serialize(&g)
   332  
   333  		switch i {
   334  		case 4:
   335  			c.Check(l, Equals, internal.Serialize([]uint16{5, 0x1f, 0, 0, 0}))
   336  		case 15:
   337  			c.Check(l, Equals, internal.Serialize([]uint16{16, 0xffff, 0, 0, 0}))
   338  		case 16:
   339  			c.Check(l, Equals, internal.Serialize([]uint16{17, 0xffff, 0x1, 0, 0}))
   340  		case 63:
   341  			c.Check(l, Equals, internal.Serialize([]uint16{64, 0xffff, 0xffff, 0xffff, 0xffff}))
   342  		}
   343  
   344  		g1, err := gr.Deserialize(l)
   345  		c.Check(err, IsNil)
   346  
   347  		c.Check(g1, DeepEquals, &g)
   348  	}
   349  
   350  	for i := uint16(63); ; i-- {
   351  		err := gr.AddTo(&g, i)
   352  		c.Assert(err, IsNil)
   353  		c.Check(gr.Contains(&g, i), Equals, true)
   354  		if i == 0 {
   355  			break
   356  		}
   357  
   358  		l := gr.Serialize(&g)
   359  
   360  		g1, err := gr.Deserialize(l)
   361  		c.Check(err, IsNil)
   362  
   363  		c.Check(g1, DeepEquals, &g)
   364  	}
   365  }
   366  
   367  func (s *groupingsSuite) TestBitsetIter(c *C) {
   368  	gr, err := internal.NewGroupings(32)
   369  	c.Assert(err, IsNil)
   370  
   371  	var elems []uint16
   372  	f := func(group uint16) error {
   373  		elems = append(elems, group)
   374  		return nil
   375  	}
   376  
   377  	for i := uint16(2); i < 32; i++ {
   378  		var g internal.Grouping
   379  
   380  		err := gr.AddTo(&g, i-2)
   381  		c.Assert(err, IsNil)
   382  		err = gr.AddTo(&g, i-1)
   383  		c.Assert(err, IsNil)
   384  		err = gr.AddTo(&g, i)
   385  		c.Assert(err, IsNil)
   386  
   387  		err = gr.Iter(&g, f)
   388  		c.Assert(err, IsNil)
   389  		c.Check(elems, DeepEquals, []uint16{i - 2, i - 1, i})
   390  
   391  		elems = nil
   392  	}
   393  
   394  	var g internal.Grouping
   395  	for i := uint16(0); i < 32; i++ {
   396  		err = gr.AddTo(&g, i)
   397  		c.Assert(err, IsNil)
   398  	}
   399  
   400  	err = gr.Iter(&g, f)
   401  	c.Assert(err, IsNil)
   402  	c.Check(elems, HasLen, 32)
   403  }
   404  
   405  func (s *groupingsSuite) TestBitsetIterError(c *C) {
   406  	gr, err := internal.NewGroupings(16)
   407  	c.Assert(err, IsNil)
   408  
   409  	var g internal.Grouping
   410  
   411  	err = gr.AddTo(&g, 0)
   412  	c.Assert(err, IsNil)
   413  	err = gr.AddTo(&g, 1)
   414  	c.Assert(err, IsNil)
   415  
   416  	errBoom := errors.New("boom")
   417  	n := 0
   418  	f := func(group uint16) error {
   419  		n++
   420  		return errBoom
   421  	}
   422  
   423  	err = gr.Iter(&g, f)
   424  	c.Check(err, Equals, errBoom)
   425  	c.Check(n, Equals, 1)
   426  }
   427  
   428  func BenchmarkIterBaseline(b *testing.B) {
   429  	b.StopTimer()
   430  
   431  	n := 0
   432  	f := func(group uint16) error {
   433  		n++
   434  		return nil
   435  	}
   436  
   437  	b.StartTimer()
   438  	for i := 0; i < b.N; i++ {
   439  		n = 0
   440  		for j := uint16(0); j < 64; j++ {
   441  			f(j)
   442  		}
   443  		if n != 64 {
   444  			b.FailNow()
   445  		}
   446  	}
   447  }
   448  
   449  func BenchmarkIter4Elems(b *testing.B) {
   450  	b.StopTimer()
   451  
   452  	gr, err := internal.NewGroupings(64)
   453  	if err != nil {
   454  		b.FailNow()
   455  	}
   456  
   457  	n := 0
   458  	f := func(group uint16) error {
   459  		n++
   460  		return nil
   461  	}
   462  
   463  	var g internal.Grouping
   464  	gr.AddTo(&g, 1)
   465  	gr.AddTo(&g, 5)
   466  	gr.AddTo(&g, 17)
   467  	gr.AddTo(&g, 24)
   468  
   469  	b.StartTimer()
   470  	for i := 0; i < b.N; i++ {
   471  		n = 0
   472  		gr.Iter(&g, f)
   473  		if n != 4 {
   474  			b.FailNow()
   475  		}
   476  	}
   477  }
   478  
   479  func BenchmarkIterBitset5Elems(b *testing.B) {
   480  	b.StopTimer()
   481  
   482  	gr, err := internal.NewGroupings(64)
   483  	if err != nil {
   484  		b.FailNow()
   485  	}
   486  
   487  	n := 0
   488  	f := func(group uint16) error {
   489  		n++
   490  		return nil
   491  	}
   492  
   493  	var g internal.Grouping
   494  	gr.AddTo(&g, 1)
   495  	gr.AddTo(&g, 5)
   496  	gr.AddTo(&g, 17)
   497  	gr.AddTo(&g, 24)
   498  	gr.AddTo(&g, 33)
   499  
   500  	b.StartTimer()
   501  	for i := 0; i < b.N; i++ {
   502  		n = 0
   503  		gr.Iter(&g, f)
   504  		if n != 5 {
   505  			b.FailNow()
   506  		}
   507  	}
   508  }
   509  
   510  func BenchmarkIterBitsetEmptyStretches(b *testing.B) {
   511  	b.StopTimer()
   512  
   513  	gr, err := internal.NewGroupings(64)
   514  	if err != nil {
   515  		b.FailNow()
   516  	}
   517  
   518  	n := 0
   519  	f := func(group uint16) error {
   520  		n++
   521  		return nil
   522  	}
   523  
   524  	var g internal.Grouping
   525  	gr.AddTo(&g, 0)
   526  	gr.AddTo(&g, 15)
   527  	gr.AddTo(&g, 16)
   528  	gr.AddTo(&g, 31)
   529  	gr.AddTo(&g, 32)
   530  
   531  	b.StartTimer()
   532  	for i := 0; i < b.N; i++ {
   533  		n = 0
   534  		gr.Iter(&g, f)
   535  		if n != 5 {
   536  			b.FailNow()
   537  		}
   538  	}
   539  }
   540  
   541  func BenchmarkIterBitsetEven(b *testing.B) {
   542  	b.StopTimer()
   543  
   544  	gr, err := internal.NewGroupings(64)
   545  	if err != nil {
   546  		b.FailNow()
   547  	}
   548  
   549  	n := 0
   550  	f := func(group uint16) error {
   551  		n++
   552  		return nil
   553  	}
   554  
   555  	var g internal.Grouping
   556  	for i := 0; i <= 63; i += 2 {
   557  		gr.AddTo(&g, uint16(i))
   558  	}
   559  
   560  	b.StartTimer()
   561  	for i := 0; i < b.N; i++ {
   562  		n = 0
   563  		gr.Iter(&g, f)
   564  		if n != 32 {
   565  			b.FailNow()
   566  		}
   567  	}
   568  }
   569  
   570  func BenchmarkIterBitsetOdd(b *testing.B) {
   571  	b.StopTimer()
   572  
   573  	gr, err := internal.NewGroupings(64)
   574  	if err != nil {
   575  		b.FailNow()
   576  	}
   577  
   578  	n := 0
   579  	f := func(group uint16) error {
   580  		n++
   581  		return nil
   582  	}
   583  
   584  	var g internal.Grouping
   585  	for i := 1; i <= 63; i += 2 {
   586  		gr.AddTo(&g, uint16(i))
   587  	}
   588  
   589  	b.StartTimer()
   590  	for i := 0; i < b.N; i++ {
   591  		n = 0
   592  		gr.Iter(&g, f)
   593  		if n != 32 {
   594  			b.FailNow()
   595  		}
   596  	}
   597  }
   598  
   599  func BenchmarkIterBitset0Inc3(b *testing.B) {
   600  	b.StopTimer()
   601  
   602  	gr, err := internal.NewGroupings(64)
   603  	if err != nil {
   604  		b.FailNow()
   605  	}
   606  
   607  	n := 0
   608  	f := func(group uint16) error {
   609  		n++
   610  		return nil
   611  	}
   612  
   613  	var g internal.Grouping
   614  	for i := 0; i <= 63; i += 3 {
   615  		gr.AddTo(&g, uint16(i))
   616  	}
   617  
   618  	b.StartTimer()
   619  	for i := 0; i < b.N; i++ {
   620  		n = 0
   621  		gr.Iter(&g, f)
   622  		if n != 22 {
   623  			b.FailNow()
   624  		}
   625  	}
   626  }
   627  
   628  func BenchmarkIterBitset1Inc3(b *testing.B) {
   629  	b.StopTimer()
   630  
   631  	gr, err := internal.NewGroupings(64)
   632  	if err != nil {
   633  		b.FailNow()
   634  	}
   635  
   636  	n := 0
   637  	f := func(group uint16) error {
   638  		n++
   639  		return nil
   640  	}
   641  
   642  	var g internal.Grouping
   643  	for i := 1; i <= 63; i += 3 {
   644  		gr.AddTo(&g, uint16(i))
   645  	}
   646  
   647  	b.StartTimer()
   648  	for i := 0; i < b.N; i++ {
   649  		n = 0
   650  		gr.Iter(&g, f)
   651  		if n != 21 {
   652  			b.FailNow()
   653  		}
   654  	}
   655  }
   656  
   657  func BenchmarkIterBitset0Inc4(b *testing.B) {
   658  	b.StopTimer()
   659  
   660  	gr, err := internal.NewGroupings(64)
   661  	if err != nil {
   662  		b.FailNow()
   663  	}
   664  
   665  	n := 0
   666  	f := func(group uint16) error {
   667  		n++
   668  		return nil
   669  	}
   670  
   671  	var g internal.Grouping
   672  	for i := 0; i <= 63; i += 4 {
   673  		gr.AddTo(&g, uint16(i))
   674  	}
   675  
   676  	b.StartTimer()
   677  	for i := 0; i < b.N; i++ {
   678  		n = 0
   679  		gr.Iter(&g, f)
   680  		if n != 16 {
   681  			b.FailNow()
   682  		}
   683  	}
   684  }
   685  
   686  func BenchmarkIterBitsetComplete(b *testing.B) {
   687  	b.StopTimer()
   688  
   689  	gr, err := internal.NewGroupings(64)
   690  	if err != nil {
   691  		b.FailNow()
   692  	}
   693  
   694  	n := 0
   695  	f := func(group uint16) error {
   696  		n++
   697  		return nil
   698  	}
   699  
   700  	var g internal.Grouping
   701  	for i := 0; i <= 63; i++ {
   702  		gr.AddTo(&g, uint16(i))
   703  	}
   704  
   705  	b.StartTimer()
   706  	for i := 0; i < b.N; i++ {
   707  		n = 0
   708  		gr.Iter(&g, f)
   709  		if n != 64 {
   710  			b.FailNow()
   711  		}
   712  	}
   713  }