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 }