github.com/teepark/go-sysvipc@v0.0.0-20200817232735-d7ca6053ea29/shm_test.go (about) 1 package sysvipc 2 3 import ( 4 "io" 5 "os" 6 "syscall" 7 "testing" 8 ) 9 10 func TestSHMErrors(t *testing.T) { 11 if _, err := GetSharedMem(0xDA7ABA5E, 64, nil); err != syscall.ENOENT { 12 t.Error("shmget without IPC_CREAT should have failed") 13 } 14 15 if _, err := (&SharedMem{5, 64}).Attach(nil); err != syscall.EINVAL && err != syscall.EIDRM { 16 t.Error("shmat on a made-up shmid should fail", err) 17 } 18 19 if err := (&SharedMem{5, 64}).Remove(); err != syscall.EINVAL && err != syscall.EIDRM { 20 t.Error("shmctl(IPC_RMID) on a made-up shmid should fail", err) 21 } 22 23 sm, err := GetSharedMem(0xDA7ABA5E, 64, &SHMFlags{ 24 Create: true, 25 Exclusive: true, 26 Perms: 0600, 27 }) 28 if err != nil { 29 t.Fatal(err) 30 } 31 defer sm.Remove() 32 mnt, err := sm.Attach(nil) 33 if err != nil { 34 t.Fatal(err) 35 } 36 if err := mnt.Close(); err != nil { 37 t.Fatal(err) 38 } 39 if err := mnt.Close(); err == nil { 40 t.Error("double close should fail") 41 } 42 } 43 44 func TestReadAndWrite(t *testing.T) { 45 shmSetup(t) 46 defer shmTeardown(t) 47 48 s := "this is a test string" 49 50 _, err := mount.Write([]byte(s)) 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 _, err = mount.Seek(0, 0) 56 if err != nil { 57 t.Fatal(err) 58 } 59 60 holder := make([]byte, len(s)) 61 _, err = mount.Read(holder) 62 if err != nil { 63 t.Error(err) 64 } 65 66 if string(holder) != s { 67 t.Errorf("mismatched text, got back %v", holder) 68 } 69 70 _, err = mount.Seek(int64(-len(s)), 2) 71 if err != nil { 72 t.Fatal(err) 73 } 74 75 b := make([]byte, len(s)*2) 76 i, err := mount.Read(b) 77 if err != io.EOF { 78 t.Error("a read that doesn't fill the buffer should give EOF", err) 79 } 80 if i != len(s) { 81 t.Error("wrong length", i) 82 } 83 84 _, err = mount.Seek(0, 2) 85 if err != nil { 86 t.Fatal(err) 87 } 88 89 i, err = mount.Read(b) 90 if err != io.EOF { 91 t.Error("a read that comes up empty should give EOF", err) 92 } 93 if i != 0 { 94 t.Error("wrong length", i) 95 } 96 97 i, err = mount.Write(b) 98 if err != io.ErrShortWrite { 99 t.Error("a write that couldn't complete should give ErrShortWrite", err) 100 } 101 if i != 0 { 102 t.Error("wrong length", i) 103 } 104 105 _, err = mount.Seek(0, 0) 106 if err != nil { 107 t.Fatal(err) 108 } 109 110 err = mount.AtomicWriteUint32(0x01020304) 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 _, err = mount.Seek(0, 0) 116 if err != nil { 117 t.Fatal(err) 118 } 119 120 v, err := mount.AtomicReadUint32() 121 if err != nil { 122 t.Fatal(err) 123 } 124 125 if v != 0x01020304 { 126 t.Errorf("Got %v, expected %v", v, 0x01020304) 127 } 128 } 129 130 func TestSHMReadOnlyError(t *testing.T) { 131 shmSetup(t) 132 defer shmTeardown(t) 133 134 roat, err := shm.Attach(&SHMAttachFlags{ReadOnly: true}) 135 if err != nil { 136 t.Fatal(err) 137 } 138 139 if _, err := roat.Write([]byte("ohai!")); err == nil { 140 t.Error("should error on write to a read-only mount", err) 141 } 142 143 if err := roat.WriteByte('+'); err == nil { 144 t.Error("should error on WriteByte to a read-only mount", err) 145 } 146 } 147 148 func TestSHMSeeks(t *testing.T) { 149 shmSetup(t) 150 defer shmTeardown(t) 151 152 i, err := mount.Seek(2048, 0) 153 if err != nil { 154 t.Fatal(err) 155 } 156 if i != 2048 { 157 t.Error("Seek to 2048 from the beginning should land at 2048", i) 158 } 159 160 j, err := mount.Seek(50, 1) 161 if err != nil { 162 t.Fatal(err) 163 } 164 if j != 2098 { 165 t.Error("Seek forward 50 should have landed at 2098", j) 166 } 167 168 k, err := mount.Seek(0, 2) 169 if err != nil { 170 t.Fatal(err) 171 } 172 if k != 4096 { 173 t.Error("Seek to end should land at 4096, the segment length", k) 174 } 175 176 _, err = mount.Seek(0, 3) 177 if err == nil { 178 t.Error("should fail on a bad 'whence'") 179 } 180 181 _, err = mount.Seek(-10, 0) 182 if err == nil { 183 t.Error("should fail when we end up at a negative index") 184 } 185 186 l, err := mount.Seek(7000, 0) 187 if err != nil { 188 t.Fatal(err) 189 } 190 if l != 4096 { 191 t.Error("should max out seeking to the end", l) 192 } 193 } 194 195 func TestSHMReadAndWriteByte(t *testing.T) { 196 shmSetup(t) 197 defer shmTeardown(t) 198 199 s := "test string" 200 for _, b := range []byte(s) { 201 if err := mount.WriteByte(b); err != nil { 202 t.Error(err) 203 } 204 } 205 206 if _, err := mount.Seek(0, 0); err != nil { 207 t.Fatal(err) 208 } 209 210 for i, b := range []byte(s) { 211 c, err := mount.ReadByte() 212 if err != nil { 213 t.Error(err) 214 } 215 216 if b != c { 217 t.Errorf("mismatched byte at position %d: %d vs %d", i, c, b) 218 } 219 } 220 221 if _, err := mount.Seek(0, 2); err != nil { 222 t.Fatal(err) 223 } 224 225 if _, err := mount.ReadByte(); err != io.EOF { 226 t.Error("attempt to ReadByte from the end should produce EOF", err) 227 } 228 229 if err := mount.WriteByte('+'); err != io.ErrShortWrite { 230 t.Error("attempt to WriteByte from the end should ErrShortWrite", err) 231 } 232 } 233 234 func TestUnreadByte(t *testing.T) { 235 shmSetup(t) 236 defer shmTeardown(t) 237 238 s := "abcdefg" 239 240 if _, err := mount.Write([]byte(s)); err != nil { 241 t.Fatal(err) 242 } 243 244 for i, c := range []byte(s) { 245 if _, err := mount.Seek(int64(i), 0); err != nil { 246 t.Fatal(err) 247 } 248 249 switch b, err := mount.ReadByte(); true { 250 case err != nil: 251 t.Error(err) 252 case b != c: 253 t.Error(i, c, b) 254 } 255 256 if err := mount.UnreadByte(); err != nil { 257 t.Error(err) 258 } 259 260 switch b, err := mount.ReadByte(); true { 261 case err != nil: 262 t.Error(err) 263 case b != c: 264 t.Error(i, c, b) 265 } 266 } 267 268 if _, err := mount.Seek(0, 0); err != nil { 269 t.Fatal(err) 270 } 271 272 if err := mount.UnreadByte(); err == nil { 273 t.Error("UnreadByte from beginning should fail", err) 274 } 275 } 276 277 func TestSHMStat(t *testing.T) { 278 shmSetup(t) 279 defer shmTeardown(t) 280 281 info, err := shm.Stat() 282 if err != nil { 283 t.Fatal(err) 284 } 285 if info.Perms.Mode&0777 != 0600 { 286 t.Error("wrong permissions", info.Perms.Mode) 287 } 288 if info.Perms.OwnerUID != os.Getuid() { 289 t.Error("wrong owner") 290 } 291 if info.Perms.CreatorUID != os.Getuid() { 292 t.Error("wrong creator") 293 } 294 if info.SegmentSize != 4096 { 295 t.Error("wrong size:", info.SegmentSize) 296 } 297 if info.CreatorPID != os.Getpid() { 298 t.Error("wrong creator pid") 299 } 300 if info.LastUserPID != os.Getpid() { 301 t.Error("wrong last user pid") 302 } 303 if info.CurrentAttaches != 1 { 304 t.Error("wrong number of attaches:", info.CurrentAttaches) 305 } 306 307 mnt2, err := shm.Attach(nil) 308 if err != nil { 309 t.Fatal(err) 310 } 311 defer mnt2.Close() 312 313 info, err = shm.Stat() 314 if err != nil { 315 t.Fatal(err) 316 } 317 if info.CurrentAttaches != 2 { 318 t.Error("didn't get the extra attach?", info.CurrentAttaches) 319 } 320 } 321 322 func TestSHMSet(t *testing.T) { 323 shmSetup(t) 324 defer shmTeardown(t) 325 326 inf, err := shm.Stat() 327 if err != nil { 328 t.Fatal(err) 329 } 330 331 err = shm.Set(&SHMInfo{ 332 Perms: IpcPerms{ 333 OwnerUID: inf.Perms.OwnerUID, 334 OwnerGID: inf.Perms.OwnerGID, 335 Mode: 0644, 336 }, 337 }) 338 if err != nil { 339 t.Fatal(err) 340 } 341 342 inf, err = shm.Stat() 343 if err != nil { 344 t.Fatal(err) 345 } 346 347 if inf.Perms.Mode&0777 != 0644 { 348 t.Error("mode change didn't take") 349 } 350 } 351 352 var ( 353 shm *SharedMem 354 mount *SharedMemMount 355 ) 356 357 func shmSetup(t *testing.T) { 358 mem, err := GetSharedMem(0xDA7ABA5E, 4096, &SHMFlags{ 359 Create: true, 360 Exclusive: true, 361 Perms: 0600, 362 }) 363 if err != nil { 364 t.Fatal(err) 365 } 366 shm = mem 367 368 mnt, err := shm.Attach(nil) 369 if err != nil { 370 t.Fatal(err) 371 } 372 mount = mnt 373 374 err = shm.Remove() 375 if err != nil { 376 t.Fatal(err) 377 } 378 } 379 380 func shmTeardown(t *testing.T) { 381 mount.Close() 382 }