github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/ext/disklayout/inode_test.go (about) 1 // Copyright 2019 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 disklayout 16 17 import ( 18 "fmt" 19 "strconv" 20 "testing" 21 22 "github.com/SagerNet/gvisor/pkg/sentry/kernel/time" 23 ) 24 25 // TestInodeSize tests that the inode structs are of the correct size. 26 func TestInodeSize(t *testing.T) { 27 var iOld InodeOld 28 assertSize(t, &iOld, OldInodeSize) 29 30 // This was updated from 156 bytes to 160 bytes in Oct 2015. 31 var iNew InodeNew 32 assertSize(t, &iNew, 160) 33 } 34 35 // TestTimestampSeconds tests that the seconds part of [a/c/m] timestamps in 36 // ext4 inode structs are decoded correctly. 37 // 38 // These tests are derived from the table under https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html#inode-timestamps. 39 func TestTimestampSeconds(t *testing.T) { 40 type timestampTest struct { 41 // msbSet tells if the most significant bit of InodeOld.[X]TimeRaw is set. 42 // If this is set then the 32-bit time is negative. 43 msbSet bool 44 45 // lowerBound tells if we should take the lowest possible value of 46 // InodeOld.[X]TimeRaw while satisfying test.msbSet condition. If set to 47 // false it tells to take the highest possible value. 48 lowerBound bool 49 50 // extraBits is InodeNew.[X]TimeExtra. 51 extraBits uint32 52 53 // want is the kernel time struct that is expected. 54 want time.Time 55 } 56 57 tests := []timestampTest{ 58 // 1901-12-13 59 { 60 msbSet: true, 61 lowerBound: true, 62 extraBits: 0, 63 want: time.FromUnix(int64(-0x80000000), 0), 64 }, 65 66 // 1969-12-31 67 { 68 msbSet: true, 69 lowerBound: false, 70 extraBits: 0, 71 want: time.FromUnix(int64(-1), 0), 72 }, 73 74 // 1970-01-01 75 { 76 msbSet: false, 77 lowerBound: true, 78 extraBits: 0, 79 want: time.FromUnix(int64(0), 0), 80 }, 81 82 // 2038-01-19 83 { 84 msbSet: false, 85 lowerBound: false, 86 extraBits: 0, 87 want: time.FromUnix(int64(0x7fffffff), 0), 88 }, 89 90 // 2038-01-19 91 { 92 msbSet: true, 93 lowerBound: true, 94 extraBits: 1, 95 want: time.FromUnix(int64(0x80000000), 0), 96 }, 97 98 // 2106-02-07 99 { 100 msbSet: true, 101 lowerBound: false, 102 extraBits: 1, 103 want: time.FromUnix(int64(0xffffffff), 0), 104 }, 105 106 // 2106-02-07 107 { 108 msbSet: false, 109 lowerBound: true, 110 extraBits: 1, 111 want: time.FromUnix(int64(0x100000000), 0), 112 }, 113 114 // 2174-02-25 115 { 116 msbSet: false, 117 lowerBound: false, 118 extraBits: 1, 119 want: time.FromUnix(int64(0x17fffffff), 0), 120 }, 121 122 // 2174-02-25 123 { 124 msbSet: true, 125 lowerBound: true, 126 extraBits: 2, 127 want: time.FromUnix(int64(0x180000000), 0), 128 }, 129 130 // 2242-03-16 131 { 132 msbSet: true, 133 lowerBound: false, 134 extraBits: 2, 135 want: time.FromUnix(int64(0x1ffffffff), 0), 136 }, 137 138 // 2242-03-16 139 { 140 msbSet: false, 141 lowerBound: true, 142 extraBits: 2, 143 want: time.FromUnix(int64(0x200000000), 0), 144 }, 145 146 // 2310-04-04 147 { 148 msbSet: false, 149 lowerBound: false, 150 extraBits: 2, 151 want: time.FromUnix(int64(0x27fffffff), 0), 152 }, 153 154 // 2310-04-04 155 { 156 msbSet: true, 157 lowerBound: true, 158 extraBits: 3, 159 want: time.FromUnix(int64(0x280000000), 0), 160 }, 161 162 // 2378-04-22 163 { 164 msbSet: true, 165 lowerBound: false, 166 extraBits: 3, 167 want: time.FromUnix(int64(0x2ffffffff), 0), 168 }, 169 170 // 2378-04-22 171 { 172 msbSet: false, 173 lowerBound: true, 174 extraBits: 3, 175 want: time.FromUnix(int64(0x300000000), 0), 176 }, 177 178 // 2446-05-10 179 { 180 msbSet: false, 181 lowerBound: false, 182 extraBits: 3, 183 want: time.FromUnix(int64(0x37fffffff), 0), 184 }, 185 } 186 187 lowerMSB0 := int32(0) // binary: 00000000 00000000 00000000 00000000 188 upperMSB0 := int32(0x7fffffff) // binary: 01111111 11111111 11111111 11111111 189 lowerMSB1 := int32(-0x80000000) // binary: 10000000 00000000 00000000 00000000 190 upperMSB1 := int32(-1) // binary: 11111111 11111111 11111111 11111111 191 192 get32BitTime := func(test timestampTest) int32 { 193 if test.msbSet { 194 if test.lowerBound { 195 return lowerMSB1 196 } 197 198 return upperMSB1 199 } 200 201 if test.lowerBound { 202 return lowerMSB0 203 } 204 205 return upperMSB0 206 } 207 208 getTestName := func(test timestampTest) string { 209 return fmt.Sprintf( 210 "Tests time decoding with epoch bits 0b%s and 32-bit raw time: MSB set=%t, lower bound=%t", 211 strconv.FormatInt(int64(test.extraBits), 2), 212 test.msbSet, 213 test.lowerBound, 214 ) 215 } 216 217 for _, test := range tests { 218 t.Run(getTestName(test), func(t *testing.T) { 219 if got := fromExtraTime(get32BitTime(test), test.extraBits); got != test.want { 220 t.Errorf("Expected: %v, Got: %v", test.want, got) 221 } 222 }) 223 } 224 }