gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/fsimpl/iouringfs/iouringfs_test.go (about) 1 // Copyright 2022 The gVisor Authors. 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 iouringfs 16 17 import ( 18 "fmt" 19 "math" 20 "strings" 21 "testing" 22 23 "gvisor.dev/gvisor/pkg/hostarch" 24 ) 25 26 func TestRoundUpPowerOfTwo(t *testing.T) { 27 tests := []struct { 28 input uint32 29 output uint32 30 }{ 31 {0, 1}, 32 {1, 1}, 33 {2, 2}, 34 {3, 4}, 35 {4, 4}, 36 {5, 8}, 37 {6, 8}, 38 {7, 8}, 39 {8, 8}, 40 {1 << 31, 2147483648}, 41 {1<<31 - 1, 2147483648}, 42 } 43 for i, tt := range tests { 44 t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { 45 s, ok := roundUpPowerOfTwo(tt.input) 46 if s != tt.output { 47 t.Errorf("Expected %d, got %d", tt.output, s) 48 } 49 if !ok { 50 t.Errorf("Expected no error, got %t. Input %d, expected %d", ok, tt.input, tt.output) 51 } 52 }) 53 } 54 } 55 56 func TestRoundUpPowerOfTwoOverflow(t *testing.T) { 57 tests := []struct { 58 input uint32 59 output uint32 60 }{ 61 {1<<31 + 1, 0}, 62 {math.MaxUint32, 0}, 63 } 64 for i, tt := range tests { 65 t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { 66 s, ok := roundUpPowerOfTwo(tt.input) 67 if s != tt.output || ok { 68 t.Errorf("Expected value %d and overflow, got %d and %t", tt.output, s, ok) 69 } 70 }) 71 } 72 } 73 74 func TestAtomicUint32AtOffset(t *testing.T) { 75 buf := make([]byte, 4096) 76 a := atomicUint32AtOffset(buf, 512) 77 78 want := uint32(123456) 79 hostarch.ByteOrder.PutUint32(buf[512:], want) 80 if a.Load() != want { 81 t.Errorf("Expected %d, got %d", want, a.Load()) 82 } 83 84 // Update value through slice. 85 want = 654321 86 hostarch.ByteOrder.PutUint32(buf[512:], want) 87 if a.Load() != want { 88 t.Errorf("Expected %d, got %d", want, a.Load()) 89 } 90 91 // Update value through pointer. 92 want = 789012 93 a.Store(want) 94 if got := hostarch.ByteOrder.Uint32(buf[512:]); got != want { 95 t.Errorf("Expected %d, got %d", want, got) 96 } 97 } 98 99 func TestUint32PtrAtOffsetEndOfSlice(t *testing.T) { 100 const sizeOfUint32 int = 4 101 buf := make([]byte, 4096) 102 103 // Cast successful at end of slice 104 _ = atomicUint32AtOffset(buf, 4096-sizeOfUint32) 105 } 106 107 func TestUint32PtrAtOffsetInvalidOffsets(t *testing.T) { 108 tests := []struct { 109 offset int 110 panicSubstr string 111 }{ 112 {1, "unaligned"}, 113 {511, "unaligned"}, 114 {-1, "overrun"}, 115 {4093, "overrun"}, 116 {4094, "overrun"}, 117 {4095, "overrun"}, 118 {4096, "overrun"}, 119 {5000, "overrun"}, 120 } 121 const sizeOfUint32 int = 4 122 123 for i, tt := range tests { 124 t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { 125 buf := make([]byte, 4096) 126 127 defer func() { 128 if r := recover(); r != nil { 129 if strings.Contains(fmt.Sprintf("%s", r), tt.panicSubstr) { 130 t.Logf("Got expected panic: %v", r) 131 return 132 } 133 134 t.Errorf("Unexpected panic: %v", r) 135 } 136 }() 137 138 _ = atomicUint32AtOffset(buf, tt.offset) 139 140 t.Errorf("Didn't get expected panic") 141 }) 142 } 143 }