-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added invalid serialization detector
- Loading branch information
1 parent
a481c35
commit 12d474c
Showing
2 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package schema | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
// NewInvalidSerializationDetectorSchema creates a new test schema type. | ||
func NewInvalidSerializationDetectorSchema() *InvalidSerializationDetectorSchema { | ||
return &InvalidSerializationDetectorSchema{} | ||
} | ||
|
||
// InvalidSerializationDetectorSchema is a testing type that detects double serialization or double unserialization, | ||
// which helps prevent bugs. | ||
// It is backed by a string, which is set to the last operation performed. If the last operation matches the | ||
// current operation, then that indicates double serialization or double unserialization. | ||
type InvalidSerializationDetectorSchema struct{} | ||
|
||
func (d InvalidSerializationDetectorSchema) Unserialize(data any) (any, error) { | ||
// The input is expected to always be a string. | ||
// If the input is equal to "unserialized", then that means it's being unserialized a second time. | ||
return d.detectInvalidValue("unserialized", data) | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) detectInvalidValue(operation string, data any) (any, error) { | ||
asString, isString := data.(string) | ||
if !isString { | ||
return nil, &ConstraintError{ | ||
Message: fmt.Sprintf( | ||
"unsupported data type for InvalidSerializationDetectorSchema; expected string, got %T", | ||
data, | ||
), | ||
} | ||
} | ||
if asString == operation { | ||
return nil, &ConstraintError{ | ||
Message: fmt.Sprintf("InvalidSerializationDetectorSchema double %s", operation), | ||
} | ||
} | ||
return operation, nil | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) UnserializeType(data any) (string, error) { | ||
unserialized, err := d.Unserialize(data) | ||
if err != nil { | ||
return "", err | ||
} | ||
return unserialized.(string), nil | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) ValidateCompatibility(_ any) error { | ||
// Not applicable to this data type | ||
return nil | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) Validate(data any) error { | ||
_, err := d.Serialize(data) | ||
return err | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) ValidateType(data string) error { | ||
return d.Validate(data) | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) Serialize(data any) (any, error) { | ||
// The input is expected to always be a string. | ||
// If the input is equal to "serialized", then that means it's being serialized a second time. | ||
return d.detectInvalidValue("serialized", data) | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) SerializeType(data string) (any, error) { | ||
return d.Serialize(data) | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) ApplyScope(scope Scope) {} | ||
|
||
func (d InvalidSerializationDetectorSchema) TypeID() TypeID { | ||
return TypeIDString // This is a subset of a string schema. | ||
} | ||
|
||
func (d InvalidSerializationDetectorSchema) ReflectedType() reflect.Type { | ||
return reflect.TypeOf("") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package schema_test | ||
|
||
import ( | ||
"go.arcalot.io/assert" | ||
"go.flow.arcalot.io/pluginsdk/schema" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestInvalidSerializationDetectorSchema_ProperUsage(t *testing.T) { | ||
schemaType := schema.NewInvalidSerializationDetectorSchema() | ||
unserialized, err := schemaType.Unserialize("original") | ||
assert.NoError(t, err) | ||
assert.Equals[any](t, unserialized, "unserialized") | ||
serialized, err := schemaType.Serialize(unserialized) | ||
assert.NoError(t, err) | ||
assert.Equals[any](t, serialized, "serialized") | ||
unserialized, err = schemaType.Unserialize(serialized) | ||
assert.NoError(t, err) | ||
assert.Equals[any](t, unserialized, "unserialized") | ||
} | ||
|
||
func TestInvalidSerializationDetectorSchema_InvalidInput(t *testing.T) { | ||
schemaType := schema.NewInvalidSerializationDetectorSchema() | ||
_, err := schemaType.Unserialize(true) | ||
assert.Error(t, err) | ||
_, err = schemaType.Serialize(true) | ||
assert.Error(t, err) | ||
} | ||
|
||
func TestInvalidSerializationDetectorSchema_DoubleSerialization(t *testing.T) { | ||
schemaType := schema.NewInvalidSerializationDetectorSchema() | ||
serialized, err := schemaType.Serialize("original") | ||
assert.NoError(t, err) | ||
_, err = schemaType.Serialize(serialized) | ||
assert.Error(t, err) | ||
assert.InstanceOf[string](t, serialized) | ||
_, err = schemaType.SerializeType(serialized.(string)) | ||
assert.Error(t, err) | ||
} | ||
|
||
func TestInvalidSerializationDetectorSchema_DoubleUnserialization(t *testing.T) { | ||
schemaType := schema.NewInvalidSerializationDetectorSchema() | ||
unserialized, err := schemaType.Unserialize("original") | ||
assert.NoError(t, err) | ||
_, err = schemaType.Unserialize(unserialized) | ||
assert.Error(t, err) | ||
_, err = schemaType.UnserializeType(unserialized) | ||
assert.Error(t, err) | ||
} | ||
|
||
func TestInvalidSerializationDetectorSchema_Other(t *testing.T) { | ||
schemaType := schema.NewInvalidSerializationDetectorSchema() | ||
// Test TypeID() | ||
assert.Equals(t, schemaType.TypeID(), schema.TypeIDString) | ||
// Test Validate and ValidateType | ||
assert.NoError(t, schemaType.Validate("any string")) | ||
assert.NoError(t, schemaType.ValidateType("any string")) | ||
// Test ReflectedType | ||
assert.Equals(t, schemaType.ReflectedType().Kind(), reflect.String) | ||
// Cover ValidateCompatibility | ||
assert.NoError(t, schemaType.ValidateCompatibility(nil)) | ||
} |