github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/imports/wasi_snapshot_preview1/environ_test.go (about)

     1  package wasi_snapshot_preview1_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/tetratelabs/wazero"
     7  	"github.com/tetratelabs/wazero/internal/testing/require"
     8  	"github.com/tetratelabs/wazero/internal/wasip1"
     9  )
    10  
    11  func Test_environGet(t *testing.T) {
    12  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().
    13  		WithEnv("a", "b").WithEnv("b", "cd"))
    14  	defer r.Close(testCtx)
    15  
    16  	resultEnvironBuf := uint32(16) // arbitrary offset
    17  	resultEnviron := uint32(26)    // arbitrary offset
    18  	expectedMemory := []byte{
    19  		'?',              // environBuf is after this
    20  		'a', '=', 'b', 0, // null terminated "a=b",
    21  		'b', '=', 'c', 'd', 0, // null terminated "b=cd"
    22  		'?',         // environ is after this
    23  		16, 0, 0, 0, // little endian-encoded offset of "a=b"
    24  		20, 0, 0, 0, // little endian-encoded offset of "b=cd"
    25  		'?', // stopped after encoding
    26  	}
    27  
    28  	maskMemory(t, mod, len(expectedMemory)+int(resultEnvironBuf))
    29  
    30  	// Invoke environGet and check the memory side effects.
    31  	requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.EnvironGetName, uint64(resultEnviron), uint64(resultEnvironBuf))
    32  	require.Equal(t, `
    33  ==> wasi_snapshot_preview1.environ_get(environ=26,environ_buf=16)
    34  <== errno=ESUCCESS
    35  `, "\n"+log.String())
    36  
    37  	actual, ok := mod.Memory().Read(resultEnvironBuf-1, uint32(len(expectedMemory)))
    38  	require.True(t, ok)
    39  	require.Equal(t, expectedMemory, actual)
    40  }
    41  
    42  func Test_environGet_Errors(t *testing.T) {
    43  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().
    44  		WithEnv("a", "bc").WithEnv("b", "cd"))
    45  	defer r.Close(testCtx)
    46  
    47  	memorySize := mod.Memory().Size()
    48  	validAddress := uint32(0) // arbitrary valid address as arguments to environ_get. We chose 0 here.
    49  
    50  	tests := []struct {
    51  		name                string
    52  		environ, environBuf uint32
    53  		expectedLog         string
    54  	}{
    55  		{
    56  			name:       "out-of-memory environ",
    57  			environ:    memorySize,
    58  			environBuf: validAddress,
    59  			expectedLog: `
    60  ==> wasi_snapshot_preview1.environ_get(environ=65536,environ_buf=0)
    61  <== errno=EFAULT
    62  `,
    63  		},
    64  		{
    65  			name:       "out-of-memory environBuf",
    66  			environ:    validAddress,
    67  			environBuf: memorySize,
    68  			expectedLog: `
    69  ==> wasi_snapshot_preview1.environ_get(environ=0,environ_buf=65536)
    70  <== errno=EFAULT
    71  `,
    72  		},
    73  		{
    74  			name: "environ exceeds the maximum valid address by 1",
    75  			// 4*envCount is the expected length for environ, 4 is the size of uint32
    76  			environ:    memorySize - 4*2 + 1,
    77  			environBuf: validAddress,
    78  			expectedLog: `
    79  ==> wasi_snapshot_preview1.environ_get(environ=65529,environ_buf=0)
    80  <== errno=EFAULT
    81  `,
    82  		},
    83  		{
    84  			name:    "environBuf exceeds the maximum valid address by 1",
    85  			environ: validAddress,
    86  			// "a=bc", "b=cd" size = size of "a=bc0b=cd0" = 10
    87  			environBuf: memorySize - 10 + 1,
    88  			expectedLog: `
    89  ==> wasi_snapshot_preview1.environ_get(environ=0,environ_buf=65527)
    90  <== errno=EFAULT
    91  `,
    92  		},
    93  	}
    94  
    95  	for _, tt := range tests {
    96  		tc := tt
    97  
    98  		t.Run(tc.name, func(t *testing.T) {
    99  			defer log.Reset()
   100  
   101  			requireErrnoResult(t, wasip1.ErrnoFault, mod, wasip1.EnvironGetName, uint64(tc.environ), uint64(tc.environBuf))
   102  			require.Equal(t, tc.expectedLog, "\n"+log.String())
   103  		})
   104  	}
   105  }
   106  
   107  func Test_environSizesGet(t *testing.T) {
   108  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().
   109  		WithEnv("a", "b").WithEnv("b", "cd"))
   110  	defer r.Close(testCtx)
   111  
   112  	resultEnvironc := uint32(16)    // arbitrary offset
   113  	resultEnvironvLen := uint32(21) // arbitrary offset
   114  	expectedMemory := []byte{
   115  		'?',                // resultEnvironc is after this
   116  		0x2, 0x0, 0x0, 0x0, // little endian-encoded environment variable count
   117  		'?',                // resultEnvironvLen is after this
   118  		0x9, 0x0, 0x0, 0x0, // little endian-encoded size of null terminated strings
   119  		'?', // stopped after encoding
   120  	}
   121  
   122  	maskMemory(t, mod, len(expectedMemory)+int(resultEnvironc))
   123  
   124  	// Invoke environSizesGet and check the memory side effects.
   125  	requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.EnvironSizesGetName, uint64(resultEnvironc), uint64(resultEnvironvLen))
   126  	require.Equal(t, `
   127  ==> wasi_snapshot_preview1.environ_sizes_get(result.environc=16,result.environv_len=21)
   128  <== errno=ESUCCESS
   129  `, "\n"+log.String())
   130  
   131  	actual, ok := mod.Memory().Read(resultEnvironc-1, uint32(len(expectedMemory)))
   132  	require.True(t, ok)
   133  	require.Equal(t, expectedMemory, actual)
   134  }
   135  
   136  func Test_environSizesGet_Errors(t *testing.T) {
   137  	mod, r, log := requireProxyModule(t, wazero.NewModuleConfig().
   138  		WithEnv("a", "b").WithEnv("b", "cd"))
   139  	defer r.Close(testCtx)
   140  
   141  	memorySize := mod.Memory().Size()
   142  	validAddress := uint32(0) // arbitrary
   143  
   144  	tests := []struct {
   145  		name                 string
   146  		environc, environLen uint32
   147  		expectedLog          string
   148  	}{
   149  		{
   150  			name:       "out-of-memory environCount",
   151  			environc:   memorySize,
   152  			environLen: validAddress,
   153  			expectedLog: `
   154  ==> wasi_snapshot_preview1.environ_sizes_get(result.environc=65536,result.environv_len=0)
   155  <== errno=EFAULT
   156  `,
   157  		},
   158  		{
   159  			name:       "out-of-memory environLen",
   160  			environc:   validAddress,
   161  			environLen: memorySize,
   162  			expectedLog: `
   163  ==> wasi_snapshot_preview1.environ_sizes_get(result.environc=0,result.environv_len=65536)
   164  <== errno=EFAULT
   165  `,
   166  		},
   167  		{
   168  			name:       "environCount exceeds the maximum valid address by 1",
   169  			environc:   memorySize - 4 + 1, // 4 is the size of uint32, the type of the count of environ
   170  			environLen: validAddress,
   171  			expectedLog: `
   172  ==> wasi_snapshot_preview1.environ_sizes_get(result.environc=65533,result.environv_len=0)
   173  <== errno=EFAULT
   174  `,
   175  		},
   176  		{
   177  			name:       "environLen exceeds the maximum valid size by 1",
   178  			environc:   validAddress,
   179  			environLen: memorySize - 4 + 1, // 4 is count of bytes to encode uint32le
   180  			expectedLog: `
   181  ==> wasi_snapshot_preview1.environ_sizes_get(result.environc=0,result.environv_len=65533)
   182  <== errno=EFAULT
   183  `,
   184  		},
   185  	}
   186  
   187  	for _, tt := range tests {
   188  		tc := tt
   189  
   190  		t.Run(tc.name, func(t *testing.T) {
   191  			defer log.Reset()
   192  
   193  			requireErrnoResult(t, wasip1.ErrnoFault, mod, wasip1.EnvironSizesGetName, uint64(tc.environc), uint64(tc.environLen))
   194  			require.Equal(t, tc.expectedLog, "\n"+log.String())
   195  		})
   196  	}
   197  }