github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/mmap/mmap_test.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 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 mmap 16 17 import ( 18 "bytes" 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "testing" 23 ) 24 25 const testMmapFile = "hi.mmap" 26 27 func TestMMap(t *testing.T) { 28 t.Log(os.Getpid()) 29 m, e := Open(testMmapFile, 32) 30 if e != nil { 31 t.Error(e) 32 } 33 34 n := m.ReadInt64At(0) 35 t.Log("read", n) 36 37 n += 20 38 m.WriteInt64At(n, 0) 39 t.Log("read", m.ReadInt64At(0)) 40 41 n = m.ReadInt64At(8) 42 t.Log("read", n) 43 44 n += 20 45 m.WriteInt64At(n, 8) 46 t.Log("read", m.ReadInt64At(8)) 47 48 n = m.ReadInt64At(16) 49 t.Log("read", n) 50 51 n += 20 52 m.WriteInt64At(n, 16) 53 t.Log("read", m.ReadInt64At(16)) 54 55 v := []byte("abcdefgh") 56 m.WriteAt(v, 24) 57 wv := m.ReadAt(24, 8) 58 t.Log("read", string(wv)) 59 os.Remove(testMmapFile) 60 } 61 62 func TestReadMmap(t *testing.T) { 63 m, e := Open(testMmapFile, 24) 64 if e != nil { 65 t.Error(e) 66 } 67 n := m.ReadInt64At(0) 68 t.Log("read", n) 69 os.Remove(testMmapFile) 70 } 71 72 var testData = []byte("0123456789ABCDEF") 73 var testPath = filepath.Join(os.TempDir(), "testdata") 74 75 func init() { 76 f := openFile(os.O_RDWR | os.O_CREATE | os.O_TRUNC) 77 f.Write(testData) 78 f.Close() 79 } 80 81 func openFile(flags int) *os.File { 82 f, err := os.OpenFile(testPath, flags, 0644) 83 if err != nil { 84 panic(err.Error()) 85 } 86 return f 87 } 88 89 func TestUnmap(t *testing.T) { 90 f := openFile(os.O_RDONLY) 91 defer f.Close() 92 m, err := Map(f, RDONLY, 0) 93 if err != nil { 94 t.Errorf("error mapping: %s", err) 95 } 96 if err := m.Unmap(); err != nil { 97 t.Errorf("error unmapping: %s", err) 98 } 99 } 100 101 func TestReadWrite(t *testing.T) { 102 f := openFile(os.O_RDWR) 103 defer f.Close() 104 m, err := Map(f, RDWR, 0) 105 if err != nil { 106 t.Errorf("error mapping: %s", err) 107 } 108 defer m.Unmap() 109 if !bytes.Equal(testData, m) { 110 t.Errorf("mmap != testData: %q, %q", m, testData) 111 } 112 113 m[9] = 'X' 114 m.Flush() 115 116 fileData, err := ioutil.ReadAll(f) 117 if err != nil { 118 t.Errorf("error reading file: %s", err) 119 } 120 if !bytes.Equal(fileData, []byte("012345678XABCDEF")) { 121 t.Errorf("file wasn't modified") 122 } 123 124 // leave things how we found them 125 m[9] = '9' 126 m.Flush() 127 } 128 129 func TestProtFlagsAndErr(t *testing.T) { 130 f := openFile(os.O_RDONLY) 131 defer f.Close() 132 if _, err := Map(f, RDWR, 0); err == nil { 133 t.Errorf("expected error") 134 } 135 } 136 137 func TestFlags(t *testing.T) { 138 f := openFile(os.O_RDWR) 139 defer f.Close() 140 m, err := Map(f, COPY, 0) 141 if err != nil { 142 t.Errorf("error mapping: %s", err) 143 } 144 defer m.Unmap() 145 146 m[9] = 'X' 147 m.Flush() 148 149 fileData, err := ioutil.ReadAll(f) 150 if err != nil { 151 t.Errorf("error reading file: %s", err) 152 } 153 if !bytes.Equal(fileData, testData) { 154 t.Errorf("file was modified") 155 } 156 } 157 158 // Test that we can map files from non-0 offsets 159 // The page size on most Unixes is 4KB, but on Windows it's 64KB 160 func TestNonZeroOffset(t *testing.T) { 161 const pageSize = 65536 162 163 // Create a 2-page sized file 164 bigFilePath := filepath.Join(os.TempDir(), "nonzero") 165 fileobj, err := os.OpenFile(bigFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) 166 if err != nil { 167 panic(err.Error()) 168 } 169 170 bigData := make([]byte, 2*pageSize, 2*pageSize) 171 fileobj.Write(bigData) 172 fileobj.Close() 173 174 // Map the first page by itself 175 fileobj, err = os.OpenFile(bigFilePath, os.O_RDONLY, 0) 176 if err != nil { 177 panic(err.Error()) 178 } 179 m, err := MapRegion(fileobj, pageSize, RDONLY, 0, 0) 180 if err != nil { 181 t.Errorf("error mapping file: %s", err) 182 } 183 m.Unmap() 184 fileobj.Close() 185 186 // Map the second page by itself 187 fileobj, err = os.OpenFile(bigFilePath, os.O_RDONLY, 0) 188 if err != nil { 189 panic(err.Error()) 190 } 191 m, err = MapRegion(fileobj, pageSize, RDONLY, 0, pageSize) 192 if err != nil { 193 t.Errorf("error mapping file: %s", err) 194 } 195 err = m.Unmap() 196 if err != nil { 197 t.Error(err) 198 } 199 200 m, err = MapRegion(fileobj, pageSize, RDONLY, 0, 1) 201 if err == nil { 202 t.Error("expect error because offset is not multiple of page size") 203 } 204 205 fileobj.Close() 206 } 207 208 func TestAnonymousMapping(t *testing.T) { 209 const size = 4 * 1024 210 211 // Make an anonymous region 212 mem, err := MapRegion(nil, size, RDWR, ANON, 0) 213 if err != nil { 214 t.Fatalf("failed to allocate memory for buffer: %v", err) 215 } 216 217 // Check memory writable 218 for i := 0; i < size; i++ { 219 mem[i] = 0x55 220 } 221 222 // And unmap it 223 err = mem.Unmap() 224 if err != nil { 225 t.Fatalf("failed to unmap memory for buffer: %v", err) 226 } 227 }