package models import ( "encoding/json" "reflect" "testing" "github.com/leanovate/gopter" "github.com/leanovate/gopter/gen" "github.com/leanovate/gopter/prop" ) var openEmptyJSON = `{"id":"","name":"","app_id":"","fn_id":"","created_at":"0001-01-01T00:00:00.000Z","updated_at":"0001-01-01T00:00:00.000Z","type":"","source":""` var triggerJSONCases = []struct { val *Trigger valString string }{ {val: &Trigger{}, valString: openEmptyJSON + "}"}, } func TestTriggerJsonMarshalling(t *testing.T) { for _, tc := range triggerJSONCases { v, err := json.Marshal(tc.val) if err != nil { t.Fatalf("Failed to marshal json into %s: %v", tc.valString, err) } if string(v) != tc.valString { t.Errorf("Invalid trigger value, expected %s, got %s", tc.valString, string(v)) } } } func TestTriggerListJsonMarshalling(t *testing.T) { emptyList := &TriggerList{Items: []*Trigger{}} expected := "{\"items\":[]}" v, err := json.Marshal(emptyList) if err != nil { t.Fatalf("Failed to marshal json into %s: %v", expected, err) } if string(v) != expected { t.Errorf("Invalid trigger value, expected %s, got %s", expected, string(v)) } } var httpTrigger = &Trigger{Name: "name", AppID: "foo", FnID: "bar", Type: "http", Source: "/baz"} var invalidTrigger = &Trigger{Name: "name", AppID: "foo", FnID: "bar", Type: "error", Source: "/baz"} var triggerValidateCases = []struct { val *Trigger valid bool }{ {val: &Trigger{}, valid: false}, {val: invalidTrigger, valid: false}, {val: httpTrigger, valid: true}, } func TestTriggerValidate(t *testing.T) { for _, tc := range triggerValidateCases { v := tc.val.Validate() if v != nil && tc.valid { t.Errorf("Expected Trigger to be valid, but err (%s) returned. Trigger: %#v", v, tc.val) } if v == nil && !tc.valid { t.Errorf("Expected Trigger to be invalid, but no err returned. Trigger: %#v", tc.val) } } } func triggerReflectType() reflect.Type { trigger := Trigger{} return reflect.TypeOf(trigger) } func triggerFieldGenerators(t *testing.T) map[string]gopter.Gen { fieldGens := make(map[string]gopter.Gen) fieldGens["ID"] = gen.AlphaString() fieldGens["Name"] = gen.AlphaString() fieldGens["AppID"] = gen.AlphaString() fieldGens["FnID"] = gen.AlphaString() fieldGens["CreatedAt"] = datetimeGenerator() fieldGens["UpdatedAt"] = datetimeGenerator() fieldGens["Type"] = gen.AlphaString() fieldGens["Source"] = gen.AlphaString() fieldGens["Annotations"] = annotationGenerator() triggerFieldCount := triggerReflectType().NumField() if triggerFieldCount != len(fieldGens) { t.Fatalf("Trigger struct field count, %d, does not match trigger generator field count, %d", triggerFieldCount, len(fieldGens)) } return fieldGens } func triggerGenerator(t *testing.T) gopter.Gen { return gen.Struct(triggerReflectType(), triggerFieldGenerators(t)) } func TestTriggerEquality(t *testing.T) { properties := gopter.NewProperties(nil) properties.Property("A trigger should always equal itself", prop.ForAll( func(trigger Trigger) bool { return trigger.Equals(&trigger) }, triggerGenerator(t), )) properties.Property("A trigger should always equal a clone of itself", prop.ForAll( func(trigger Trigger) bool { clone := trigger.Clone() return trigger.Equals(clone) }, triggerGenerator(t), )) triggerFieldGens := triggerFieldGenerators(t) properties.Property("A trigger should never match a modified version of itself", prop.ForAll( func(trigger Trigger) bool { for fieldName, fieldGen := range triggerFieldGens { if fieldName == "CreatedAt" || fieldName == "UpdatedAt" { continue } currentValue, newValue := novelValue(t, reflect.ValueOf(trigger), fieldName, fieldGen) clone := trigger.Clone() s := reflect.ValueOf(clone).Elem() field := s.FieldByName(fieldName) field.Set(newValue) if trigger.Equals(clone) { t.Errorf("Changed field, %s, from {%v} to {%v}, but still equal.", fieldName, currentValue, newValue) return false } } return true }, triggerGenerator(t), )) properties.TestingRun(t) }