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  }