gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/state/tests/register_test.go (about)

     1  // Copyright 2018 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  //go:build race
    16  // +build race
    17  
    18  package tests
    19  
    20  import (
    21  	"context"
    22  	"testing"
    23  
    24  	"gvisor.dev/gvisor/pkg/state"
    25  )
    26  
    27  // faker calls itself whatever is in the name field.
    28  type faker struct {
    29  	Name   string
    30  	Fields []string
    31  }
    32  
    33  func (f *faker) StateTypeName() string {
    34  	return f.Name
    35  }
    36  
    37  func (f *faker) StateFields() []string {
    38  	return f.Fields
    39  }
    40  
    41  // fakerWithSaverLoader has all it needs.
    42  type fakerWithSaverLoader struct {
    43  	faker
    44  }
    45  
    46  func (f *fakerWithSaverLoader) StateSave(m state.Sink) {}
    47  
    48  func (f *fakerWithSaverLoader) StateLoad(_ context.Context, m state.Source) {}
    49  
    50  // fakerOther calls itself .. uh, itself?
    51  type fakerOther string
    52  
    53  func (f *fakerOther) StateTypeName() string {
    54  	return string(*f)
    55  }
    56  
    57  func (f *fakerOther) StateFields() []string {
    58  	return nil
    59  }
    60  
    61  func newFakerOther(name string) *fakerOther {
    62  	f := fakerOther(name)
    63  	return &f
    64  }
    65  
    66  // fakerOtherBadFields returns non-nil fields.
    67  type fakerOtherBadFields string
    68  
    69  func (f *fakerOtherBadFields) StateTypeName() string {
    70  	return string(*f)
    71  }
    72  
    73  func (f *fakerOtherBadFields) StateFields() []string {
    74  	return []string{string(*f)}
    75  }
    76  
    77  func newFakerOtherBadFields(name string) *fakerOtherBadFields {
    78  	f := fakerOtherBadFields(name)
    79  	return &f
    80  }
    81  
    82  // fakerOtherSaverLoader implements SaverLoader methods.
    83  type fakerOtherSaverLoader string
    84  
    85  func (f *fakerOtherSaverLoader) StateTypeName() string {
    86  	return string(*f)
    87  }
    88  
    89  func (f *fakerOtherSaverLoader) StateFields() []string {
    90  	return nil
    91  }
    92  
    93  func (f *fakerOtherSaverLoader) StateSave(m state.Sink) {}
    94  
    95  func (f *fakerOtherSaverLoader) StateLoad(_ context.Context, m state.Source) {}
    96  
    97  func newFakerOtherSaverLoader(name string) *fakerOtherSaverLoader {
    98  	f := fakerOtherSaverLoader(name)
    99  	return &f
   100  }
   101  
   102  func TestRegisterPrimitives(t *testing.T) {
   103  	for _, typeName := range []string{
   104  		"int",
   105  		"int8",
   106  		"int16",
   107  		"int32",
   108  		"int64",
   109  		"uint",
   110  		"uintptr",
   111  		"uint8",
   112  		"uint16",
   113  		"uint32",
   114  		"uint64",
   115  		"float32",
   116  		"float64",
   117  		"complex64",
   118  		"complex128",
   119  		"string",
   120  	} {
   121  		t.Run("struct/"+typeName, func(t *testing.T) {
   122  			defer func() {
   123  				if r := recover(); r == nil {
   124  					t.Errorf("Registering type %q did not panic", typeName)
   125  				}
   126  			}()
   127  			state.Register(&faker{
   128  				Name: typeName,
   129  			})
   130  		})
   131  		t.Run("other/"+typeName, func(t *testing.T) {
   132  			defer func() {
   133  				if r := recover(); r == nil {
   134  					t.Errorf("Registering type %q did not panic", typeName)
   135  				}
   136  			}()
   137  			state.Register(newFakerOther(typeName))
   138  		})
   139  	}
   140  }
   141  
   142  func TestRegisterBad(t *testing.T) {
   143  	const (
   144  		goodName    = "foo"
   145  		firstField  = "a"
   146  		secondField = "b"
   147  	)
   148  	for name, object := range map[string]state.Type{
   149  		"non-struct-with-fields":                  newFakerOtherBadFields(goodName),
   150  		"non-struct-with-saverloader":             newFakerOtherSaverLoader(goodName),
   151  		"struct-without-saverloader":              &faker{Name: goodName},
   152  		"non-struct-duplicate-with-struct":        newFakerOther((new(alreadyRegisteredStruct)).StateTypeName()),
   153  		"non-struct-duplicate-with-non-struct":    newFakerOther((new(alreadyRegisteredOther)).StateTypeName()),
   154  		"struct-duplicate-with-struct":            &fakerWithSaverLoader{faker{Name: (new(alreadyRegisteredStruct)).StateTypeName()}},
   155  		"struct-duplicate-with-non-struct":        &fakerWithSaverLoader{faker{Name: (new(alreadyRegisteredOther)).StateTypeName()}},
   156  		"struct-with-empty-field":                 &fakerWithSaverLoader{faker{Name: goodName, Fields: []string{""}}},
   157  		"struct-with-empty-field-and-non-empty":   &fakerWithSaverLoader{faker{Name: goodName, Fields: []string{firstField, ""}}},
   158  		"struct-with-duplicate-field":             &fakerWithSaverLoader{faker{Name: goodName, Fields: []string{firstField, firstField}}},
   159  		"struct-with-duplicate-field-and-non-dup": &fakerWithSaverLoader{faker{Name: goodName, Fields: []string{firstField, secondField, firstField}}},
   160  	} {
   161  		t.Run(name, func(t *testing.T) {
   162  			defer func() {
   163  				if r := recover(); r == nil {
   164  					t.Errorf("Registering object %#v did not panic", object)
   165  				}
   166  			}()
   167  			state.Register(object)
   168  		})
   169  
   170  	}
   171  }
   172  
   173  func TestRegisterTypeOnlyStruct(t *testing.T) {
   174  	defer func() {
   175  		if r := recover(); r == nil {
   176  			t.Errorf("Register did not panic")
   177  		}
   178  	}()
   179  	state.Register((*typeOnlyEmptyStruct)(nil))
   180  }