github.com/gaukas/goofys100m@v0.24.0/internal/buffer_pool_test.go (about)

     1  // Copyright 2015 - 2017 Ka-Hing Cheung
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package internal
    16  
    17  import (
    18  	"bytes"
    19  	"io"
    20  	"io/ioutil"
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/sirupsen/logrus"
    25  	. "gopkg.in/check.v1"
    26  )
    27  
    28  type BufferTest struct {
    29  }
    30  
    31  var _ = Suite(&BufferTest{})
    32  var ignored2 = logrus.DebugLevel
    33  
    34  type SeqReader struct {
    35  	cur int64
    36  }
    37  
    38  func (r *SeqReader) Read(p []byte) (n int, err error) {
    39  	n = len(p)
    40  	for i := range p {
    41  		r.cur++
    42  		p[i] = byte(r.cur)
    43  	}
    44  
    45  	return
    46  }
    47  
    48  func (r *SeqReader) Seek(offset int64, whence int) (int64, error) {
    49  	switch whence {
    50  	case 0:
    51  		r.cur = offset
    52  	case 1:
    53  		r.cur += offset
    54  	default:
    55  		panic("unsupported whence")
    56  	}
    57  
    58  	return r.cur, nil
    59  
    60  }
    61  
    62  type SlowReader struct {
    63  	r     io.Reader
    64  	sleep time.Duration
    65  }
    66  
    67  func (r *SlowReader) Read(p []byte) (n int, err error) {
    68  	time.Sleep(r.sleep)
    69  	return r.r.Read(p[:MinInt(len(p), 1336)])
    70  }
    71  
    72  func (r *SlowReader) Close() error {
    73  	if reader, ok := r.r.(io.ReadCloser); ok {
    74  		return reader.Close()
    75  	}
    76  	return nil
    77  }
    78  
    79  func CompareReader(r1, r2 io.Reader, bufSize int) (int, error) {
    80  	if bufSize == 0 {
    81  		bufSize = 1337
    82  	}
    83  	buf1 := make([]byte, bufSize)
    84  	buf2 := make([]byte, bufSize)
    85  
    86  	for {
    87  		nread, err := r1.Read(buf1[:])
    88  		if err != nil && err != io.EOF {
    89  			return -1, err
    90  		}
    91  
    92  		if nread == 0 {
    93  			break
    94  		}
    95  
    96  		nread2, err2 := io.ReadFull(r2, buf2[:nread])
    97  		if err2 != nil && err != err2 {
    98  			return -1, err2
    99  		}
   100  
   101  		if bytes.Compare(buf1[:], buf2[:]) != 0 {
   102  			// fallback to slow path to find the exact point of divergent
   103  			for i, b := range buf1 {
   104  				if buf2[i] != b {
   105  					return i, nil
   106  				}
   107  			}
   108  
   109  			if nread2 > nread {
   110  				return nread, nil
   111  			}
   112  		}
   113  	}
   114  
   115  	// should have consumed all of r2
   116  	nread2, err := r2.Read(buf2[:])
   117  	if nread2 == 0 || err == io.ErrUnexpectedEOF {
   118  		return -1, nil
   119  	} else {
   120  		if err == io.EOF {
   121  			err = nil
   122  		}
   123  		return nread2, err
   124  	}
   125  }
   126  
   127  func (s *BufferTest) TestMBuf(t *C) {
   128  	h := NewBufferPool(1000 * 1024 * 1024)
   129  
   130  	n := uint64(2 * BUF_SIZE)
   131  	mb := MBuf{}.Init(h, n, false)
   132  	t.Assert(len(mb.buffers), Equals, 2)
   133  
   134  	r := io.LimitReader(&SeqReader{}, int64(n))
   135  
   136  	for {
   137  		nread, err := mb.WriteFrom(r)
   138  		t.Assert(err, IsNil)
   139  		if nread == 0 {
   140  			break
   141  		}
   142  	}
   143  	t.Assert(mb.wbuf, Equals, 1)
   144  	t.Assert(mb.wp, Equals, BUF_SIZE)
   145  
   146  	diff, err := CompareReader(mb, io.LimitReader(&SeqReader{}, int64(n)), 0)
   147  	t.Assert(err, IsNil)
   148  	t.Assert(diff, Equals, -1)
   149  
   150  	t.Assert(mb.rbuf, Equals, 1)
   151  	t.Assert(mb.rp, Equals, BUF_SIZE)
   152  
   153  	t.Assert(h.numBuffers, Equals, uint64(2))
   154  	mb.Free()
   155  	t.Assert(h.numBuffers, Equals, uint64(0))
   156  }
   157  
   158  func (s *BufferTest) TestBufferWrite(t *C) {
   159  	h := NewBufferPool(1000 * 1024 * 1024)
   160  
   161  	n := uint64(2 * BUF_SIZE)
   162  	mb := MBuf{}.Init(h, n, true)
   163  	t.Assert(len(mb.buffers), Equals, 2)
   164  
   165  	nwritten, err := io.Copy(mb, io.LimitReader(&SeqReader{}, int64(n)))
   166  	t.Assert(nwritten, Equals, int64(n))
   167  	t.Assert(err, IsNil)
   168  
   169  	diff, err := CompareReader(mb, io.LimitReader(&SeqReader{}, int64(n)), 0)
   170  	t.Assert(err, IsNil)
   171  	t.Assert(diff, Equals, -1)
   172  
   173  	cur, err := mb.Seek(0, 1)
   174  	t.Assert(err, IsNil)
   175  	t.Assert(cur, Equals, int64(n))
   176  
   177  	cur, err = mb.Seek(0, 2)
   178  	t.Assert(err, IsNil)
   179  	t.Assert(cur, Equals, int64(n))
   180  
   181  	cur, err = mb.Seek(0, 0)
   182  	t.Assert(err, IsNil)
   183  	t.Assert(cur, Equals, int64(0))
   184  	t.Assert(mb.rbuf, Equals, 0)
   185  	t.Assert(mb.rp, Equals, 0)
   186  
   187  	diff, err = CompareReader(mb, io.LimitReader(&SeqReader{}, int64(n)), 0)
   188  	t.Assert(err, IsNil)
   189  	t.Assert(diff, Equals, -1)
   190  }
   191  
   192  func (s *BufferTest) TestBufferLen(t *C) {
   193  	h := NewBufferPool(1000 * 1024 * 1024)
   194  
   195  	n := uint64(2*BUF_SIZE - 1)
   196  	mb := MBuf{}.Init(h, n, true)
   197  	t.Assert(len(mb.buffers), Equals, 2)
   198  
   199  	nwritten, err := io.Copy(mb, io.LimitReader(&SeqReader{}, int64(n)))
   200  	t.Assert(nwritten, Equals, int64(n))
   201  	t.Assert(err, IsNil)
   202  	t.Assert(mb.Len(), Equals, int(n))
   203  }
   204  
   205  func (s *BufferTest) TestBuffer(t *C) {
   206  	h := NewBufferPool(1000 * 1024 * 1024)
   207  
   208  	n := uint64(2 * BUF_SIZE)
   209  	mb := MBuf{}.Init(h, n, false)
   210  	t.Assert(len(mb.buffers), Equals, 2)
   211  
   212  	r := func() (io.ReadCloser, error) {
   213  		return &SlowReader{io.LimitReader(&SeqReader{}, int64(n)), 1 * time.Millisecond}, nil
   214  	}
   215  
   216  	b := Buffer{}.Init(mb, r)
   217  
   218  	diff, err := CompareReader(b, io.LimitReader(&SeqReader{}, int64(n)), 0)
   219  	t.Assert(err, IsNil)
   220  	t.Assert(diff, Equals, -1)
   221  	t.Assert(b.buf, IsNil)
   222  	t.Assert(b.reader, NotNil)
   223  	t.Assert(h.numBuffers, Equals, uint64(0))
   224  }
   225  
   226  // io.Limitedreader does not return EOF the first time limit is
   227  // reached, unlike the reader you get from http
   228  type OneByteReader struct {
   229  	read bool
   230  }
   231  
   232  func (r *OneByteReader) Read(p []byte) (n int, err error) {
   233  	err = io.EOF
   234  	if r.read {
   235  		return
   236  	}
   237  	p[0] = 1
   238  	n = 1
   239  	r.read = true
   240  	return
   241  }
   242  
   243  func (s *BufferTest) TestBufferTiny(t *C) {
   244  	h := NewBufferPool(1000 * 1024 * 1024)
   245  
   246  	n := uint64(1)
   247  	mb := MBuf{}.Init(h, n, false)
   248  	t.Assert(len(mb.buffers), Equals, 1)
   249  
   250  	r := func() (io.ReadCloser, error) {
   251  		return ioutil.NopCloser(&OneByteReader{}), nil
   252  	}
   253  
   254  	b := Buffer{}.Init(mb, r)
   255  
   256  	diff, err := CompareReader(b, &OneByteReader{}, 0)
   257  	t.Assert(err, IsNil)
   258  	t.Assert(diff, Equals, -1)
   259  	t.Assert(b.buf, IsNil)
   260  	t.Assert(b.reader, NotNil)
   261  	t.Assert(h.numBuffers, Equals, uint64(0))
   262  }
   263  
   264  func (s *BufferTest) TestPool(t *C) {
   265  	const MAX = 8
   266  	pool := BufferPool{maxBuffers: MAX}.Init()
   267  	var wg sync.WaitGroup
   268  
   269  	for i := 0; i < 10; i++ {
   270  		wg.Add(1)
   271  		go func() {
   272  			var inner sync.WaitGroup
   273  			for j := 0; j < 30; j++ {
   274  				inner.Add(1)
   275  				buf := pool.RequestBuffer()
   276  				go func() {
   277  					time.Sleep(1000 * time.Millisecond)
   278  					pool.Free(buf)
   279  					inner.Done()
   280  				}()
   281  				inner.Wait()
   282  			}
   283  			wg.Done()
   284  		}()
   285  	}
   286  
   287  	wg.Wait()
   288  }
   289  
   290  func (s *BufferTest) TestIssue193(t *C) {
   291  	h := NewBufferPool(1000 * 1024 * 1024)
   292  
   293  	n := uint64(2 * BUF_SIZE)
   294  	mb := MBuf{}.Init(h, n, false)
   295  
   296  	r := func() (io.ReadCloser, error) {
   297  		return &SlowReader{io.LimitReader(&SeqReader{}, int64(n)), 1 * time.Millisecond}, nil
   298  	}
   299  
   300  	b := Buffer{}.Init(mb, r)
   301  	b.Close()
   302  
   303  	// readloop would have caused a panic
   304  }
   305  
   306  func (s *BufferTest) TestCGroupMemory(t *C) {
   307  	//test getMemoryCgroupPath()
   308  	test_input := `11:hugetlb:/
   309                      10:memory:/user.slice
   310                      9:cpuset:/
   311                      8:blkio:/user.slice
   312                      7:perf_event:/
   313                      6:net_prio,net_cls:/
   314                      5:cpuacct,cpu:/user.slice
   315                      4:devices:/user.slice
   316                      3:freezer:/
   317                      2:pids:/
   318                      1:name=systemd:/user.slice/user-1000.slice/session-1759.scope`
   319  	mem_path, _ := getMemoryCgroupPath(test_input)
   320  	t.Assert(mem_path, Equals, "/user.slice")
   321  }