gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/osutil/cmp_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-2015 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 osutil_test 21 22 import ( 23 "bytes" 24 "io/ioutil" 25 "os" 26 "path/filepath" 27 "strings" 28 29 . "gopkg.in/check.v1" 30 31 "github.com/snapcore/snapd/osutil" 32 ) 33 34 type CmpTestSuite struct{} 35 36 var _ = Suite(&CmpTestSuite{}) 37 38 func (ts *CmpTestSuite) TestCmp(c *C) { 39 tmpdir := c.MkDir() 40 41 foo := filepath.Join(tmpdir, "foo") 42 f, err := os.Create(foo) 43 c.Assert(err, IsNil) 44 defer f.Close() 45 46 // test FilesAreEqual for various sizes: 47 // - bufsz not exceeded 48 // - bufsz matches file size 49 // - bufsz exceeds file size 50 canary := "1234567890123456" 51 for _, n := range []int{1, 128 / len(canary), (128 / len(canary)) + 1} { 52 for i := 0; i < n; i++ { 53 // Pick a smaller buffer size so that the test can complete quicker 54 c.Assert(osutil.FilesAreEqualChunked(foo, foo, 128), Equals, true) 55 _, err := f.WriteString(canary) 56 c.Assert(err, IsNil) 57 f.Sync() 58 } 59 } 60 } 61 62 func (ts *CmpTestSuite) TestCmpEmptyNeqMissing(c *C) { 63 tmpdir := c.MkDir() 64 65 foo := filepath.Join(tmpdir, "foo") 66 bar := filepath.Join(tmpdir, "bar") 67 f, err := os.Create(foo) 68 c.Assert(err, IsNil) 69 defer f.Close() 70 c.Assert(osutil.FilesAreEqual(foo, bar), Equals, false) 71 c.Assert(osutil.FilesAreEqual(bar, foo), Equals, false) 72 } 73 74 func (ts *CmpTestSuite) TestCmpEmptyNeqNonEmpty(c *C) { 75 tmpdir := c.MkDir() 76 77 foo := filepath.Join(tmpdir, "foo") 78 bar := filepath.Join(tmpdir, "bar") 79 f, err := os.Create(foo) 80 c.Assert(err, IsNil) 81 defer f.Close() 82 c.Assert(ioutil.WriteFile(bar, []byte("x"), 0644), IsNil) 83 c.Assert(osutil.FilesAreEqual(foo, bar), Equals, false) 84 c.Assert(osutil.FilesAreEqual(bar, foo), Equals, false) 85 } 86 87 func (ts *CmpTestSuite) TestCmpStreams(c *C) { 88 for _, x := range []struct { 89 a string 90 b string 91 r bool 92 }{ 93 {"hello", "hello", true}, 94 {"hello", "world", false}, 95 {"hello", "hell", false}, 96 } { 97 c.Assert(osutil.StreamsEqual(strings.NewReader(x.a), strings.NewReader(x.b)), Equals, x.r) 98 } 99 } 100 101 func (s *CmpTestSuite) TestStreamsEqualChunked(c *C) { 102 text := "marry had a little lamb" 103 104 // Passing the same stream twice is not mishandled. 105 readerA := bytes.NewReader([]byte(text)) 106 readerB := readerA 107 eq := osutil.StreamsEqualChunked(readerA, readerB, 0) 108 c.Check(eq, Equals, true) 109 110 // Passing two streams with the same content works as expected. Note that 111 // we are using different block sizes to check for additional edge cases. 112 for _, chunkSize := range []int{0, 1, len(text) / 2, len(text), len(text) + 1} { 113 readerA = bytes.NewReader([]byte(text)) 114 readerB = bytes.NewReader([]byte(text)) 115 eq := osutil.StreamsEqualChunked(readerA, readerB, chunkSize) 116 c.Check(eq, Equals, true, Commentf("chunk size %d", chunkSize)) 117 } 118 119 // Passing two streams with unequal contents but equal length works as 120 // expected. 121 for _, chunkSize := range []int{0, 1, len(text) / 2, len(text), len(text) + 1} { 122 comment := Commentf("chunk size %d", chunkSize) 123 readerA = bytes.NewReader([]byte(strings.ToLower(text))) 124 readerB = bytes.NewReader([]byte(strings.ToUpper(text))) 125 eq = osutil.StreamsEqualChunked(readerA, readerB, chunkSize) 126 c.Check(eq, Equals, false, comment) 127 } 128 129 // Passing two streams which differer by tail only also works as expected. 130 for _, chunkSize := range []int{0, 1, len(text) / 2, len(text), len(text) + 1} { 131 textWithChangedTail := text[:len(text)-1] + strings.ToUpper(text[len(text)-1:]) 132 c.Assert(textWithChangedTail, Not(Equals), text) 133 c.Assert(len(textWithChangedTail), Equals, len(text)) 134 comment := Commentf("chunk size %d", chunkSize) 135 readerA = bytes.NewReader([]byte(text)) 136 readerB = bytes.NewReader([]byte(textWithChangedTail)) 137 eq = osutil.StreamsEqualChunked(readerA, readerB, chunkSize) 138 c.Check(eq, Equals, false, comment) 139 } 140 141 // Passing two streams with different length works as expected. 142 // Note that this is not used by EnsureDirState in practice. 143 for _, chunkSize := range []int{0, 1, len(text) / 2, len(text), len(text) + 1} { 144 comment := Commentf("A: %q, B: %q, chunk size %d", text, text[:len(text)/2], chunkSize) 145 readerA = bytes.NewReader([]byte(text)) 146 readerB = bytes.NewReader([]byte(text[:len(text)/2])) 147 eq = osutil.StreamsEqualChunked(readerA, readerB, chunkSize) 148 c.Check(eq, Equals, false, comment) 149 150 // Readers passed the other way around. 151 readerA = bytes.NewReader([]byte(text)) 152 readerB = bytes.NewReader([]byte(text[:len(text)/2])) 153 eq = osutil.StreamsEqualChunked(readerB, readerA, chunkSize) 154 c.Check(eq, Equals, false, comment) 155 } 156 }