From 59a5df253fd209a40488fed272578348d12fc2c7 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Wed, 26 Jun 2019 20:31:59 +0200 Subject: [PATCH] Better record value sanitization, refactor & split tests --- compose/internal/repository/record_test.go | 62 ++-- compose/internal/service/record.go | 25 +- .../service/record_integration_test.go | 253 +++++++++++++++ compose/internal/service/record_test.go | 290 ++---------------- 4 files changed, 334 insertions(+), 296 deletions(-) create mode 100644 compose/internal/service/record_integration_test.go diff --git a/compose/internal/repository/record_test.go b/compose/internal/repository/record_test.go index 62e4a2e6d..51dd9e283 100644 --- a/compose/internal/repository/record_test.go +++ b/compose/internal/repository/record_test.go @@ -1,8 +1,7 @@ package repository -/* - import ( + "fmt" "strings" "testing" @@ -10,17 +9,11 @@ import ( "github.com/cortezaproject/corteza-server/internal/test" ) -*/ - -// This test is a moving target, it doesn't do any good to -// test the generated sql query, as you'd need an integration -// test to verify that it works correctly. - -/* func TestRecordFinder(t *testing.T) { r := record{} m := &types.Module{ - ID: 123, + ID: 123, + NamespaceID: 456, Fields: types.ModuleFieldSet{ &types.ModuleField{Name: "foo"}, &types.ModuleField{Name: "bar"}, @@ -28,30 +21,40 @@ func TestRecordFinder(t *testing.T) { } ttc := []struct { - filter string - sort string - match []string - args []interface{} + f types.RecordFilter + match []string + args []interface{} + err error }{ { - match: []string{"SELECT * FROM crm_record AS r WHERE r.module_id = ? AND r.deleted_at IS NULL"}, - args: []interface{}{123}}, + match: []string{"SELECT * FROM compose_record AS r WHERE r.deleted_at IS NULL AND r.module_id = ?"}, + }, { - filter: "id = 5 AND foo = 7", + f: types.RecordFilter{Filter: "id = 5 AND foo = 7"}, match: []string{ - " AND id = 5", - " AND (SELECT value FROM crm_record_value WHERE name = ? AND record_id = crm_record.id AND deleted_at IS NULL) = 7"}, - args: []interface{}{123}}, + "id = 5", + "rv_foo.value = 7"}, + args: []interface{}{"foo"}, + }, { - sort: "id ASC, foo DESC", + f: types.RecordFilter{Sort: "id ASC, bar DESC"}, match: []string{ - " id ASC, (SELECT value FROM crm_record_value WHERE name = 'foo' AND record_id = crm_record.id AND deleted_at IS NULL) DESC"}, - args: []interface{}{123}}, + " id ASC", + " rv_bar.value DESC", + }, + args: []interface{}{"bar"}, + }, } for _, tc := range ttc { - sb, err := r.buildQuery(m, tc.filter, tc.sort) - test.Assert(t, err == nil, "buildQuery(%q, %q) returned an error: %v", tc.filter, tc.sort, err) + sb, err := r.buildQuery(m, tc.f) + + if tc.err != nil { + test.Assert(t, tc.err.Error() == fmt.Sprintf("%v", err), "buildQuery(%+v) did not return an expected error %q but %q", tc.f, tc.err, err) + } else { + test.Assert(t, err == nil, "buildQuery(%+v) returned an unexpected error: %v", tc.f, err) + } + sb = sb.Column("*") sql, args, err := sb.ToSql() @@ -61,10 +64,9 @@ func TestRecordFinder(t *testing.T) { " did not contain %q", sql, m) } - _ = args - // test.Assert(t, reflect.DeepEqual(args, tc.args), - // "assertion failed; args %v \n "+ - // " do not match expected %v", args, tc.args) + tc.args = append(tc.args, m.ID, m.NamespaceID) + test.Assert(t, fmt.Sprintf("%+v", args) == fmt.Sprintf("%+v", tc.args), + "assertion failed; args %+v \n "+ + " do not match expected %+v", args, tc.args) } } -*/ diff --git a/compose/internal/service/record.go b/compose/internal/service/record.go index 0825bcd43..6ecc42175 100644 --- a/compose/internal/service/record.go +++ b/compose/internal/service/record.go @@ -2,6 +2,7 @@ package service import ( "context" + "regexp" "strconv" "time" @@ -161,7 +162,7 @@ func (svc record) Create(mod *types.Record) (r *types.Record, err error) { return nil, ErrNoCreatePermissions.withStack() } - if err = svc.sanitizeValues(m, mod.Values); err != nil { + if mod.Values, err = svc.sanitizeValues(m, mod.Values); err != nil { return } @@ -212,7 +213,7 @@ func (svc record) Update(mod *types.Record) (r *types.Record, err error) { return nil, ErrStaleData.withStack() } - if err = svc.sanitizeValues(m, mod.Values); err != nil { + if mod.Values, err = svc.sanitizeValues(m, mod.Values); err != nil { return } @@ -268,7 +269,7 @@ func (svc record) DeleteByID(namespaceID, recordID uint64) (err error) { } // Validates and filters record values -func (svc record) sanitizeValues(module *types.Module, values types.RecordValueSet) (err error) { +func (svc record) sanitizeValues(module *types.Module, values types.RecordValueSet) (out types.RecordValueSet, err error) { // Make sure there are no multi values in a non-multi value fields err = module.Fields.Walk(func(field *types.ModuleField) error { if !field.Multi && len(values.FilterByName(field.Name)) > 1 { @@ -282,12 +283,17 @@ func (svc record) sanitizeValues(module *types.Module, values types.RecordValueS } // Remove all values on un-updatable fields - values, err = values.Filter(func(v *types.RecordValue) (bool, error) { + out, err = values.Filter(func(v *types.RecordValue) (bool, error) { var field = module.Fields.FindByName(v.Name) if field == nil { return false, errors.Errorf("no such field %q", v.Name) } + if field.IsRef() && v.Value == "" { + // Skip empty values on ref fields + return false, nil + } + return svc.ac.CanUpdateRecordValue(svc.ctx, field), nil }) @@ -295,15 +301,22 @@ func (svc record) sanitizeValues(module *types.Module, values types.RecordValueS return } - var places = map[string]uint{} + var ( + places = map[string]uint{} + numeric = regexp.MustCompile(`^(\d+)$`) + ) - return values.Walk(func(value *types.RecordValue) (err error) { + return out, out.Walk(func(value *types.RecordValue) (err error) { var field = module.Fields.FindByName(value.Name) if field == nil { return errors.Errorf("no such field %q", value.Name) } if field.IsRef() { + if !numeric.MatchString(value.Value) { + return errors.Errorf("invalid reference format") + } + if value.Ref, err = strconv.ParseUint(value.Value, 10, 64); err != nil { return err } diff --git a/compose/internal/service/record_integration_test.go b/compose/internal/service/record_integration_test.go new file mode 100644 index 000000000..0ed711c29 --- /dev/null +++ b/compose/internal/service/record_integration_test.go @@ -0,0 +1,253 @@ +// +build integration + +package service + +import ( + "context" + "testing" + + "github.com/titpetric/factory" + + "github.com/cortezaproject/corteza-server/compose/types" + "github.com/cortezaproject/corteza-server/internal/auth" + "github.com/cortezaproject/corteza-server/internal/permissions" + "github.com/cortezaproject/corteza-server/internal/test" +) + +func TestRecord(t *testing.T) { + factory.Database.MustGet("compose").Profiler = newTestLogProfiler(t) + + ctx := context.WithValue(context.Background(), "testing", true) + + ctx = auth.SetIdentityToContext(ctx, auth.NewIdentity(1337)) + + var err error + ns1, ns2 := createTestNamespaces(ctx, t) + + moduleSvc := Module().With(ctx) + svc := Record().With(ctx) + svc.(*record).ac = AccessControl(&permissions.ServiceAllowAll{}) + + module1 := &types.Module{ + NamespaceID: ns1.ID, + Name: "Test", + Fields: types.ModuleFieldSet{ + &types.ModuleField{ + Name: "name", + }, + &types.ModuleField{ + Name: "email", + }, + &types.ModuleField{ + Name: "options", + Multi: true, + }, + &types.ModuleField{ + Name: "description", + }, + &types.ModuleField{ + Name: "another_record", + Kind: "Record", + }, + }, + } + + // set up a module1 + module1, err = moduleSvc.Create(module1) + test.Assert(t, err == nil, "Error when creating module1: %+v", err) + test.Assert(t, module1.ID > 0, "Expected auto generated ID") + + module2 := &types.Module{ + NamespaceID: ns2.ID, + Name: "Test Dummy", + Fields: types.ModuleFieldSet{ + &types.ModuleField{ + Name: "name", + }, + &types.ModuleField{ + Name: "email", + }, + &types.ModuleField{ + Name: "options", + Multi: true, + }, + &types.ModuleField{ + Name: "description", + }, + &types.ModuleField{ + Name: "another_record", + Kind: "Record", + }, + }, + } + module2, err = moduleSvc.Create(module2) + test.Assert(t, err == nil, "Error when creating module1 in another namespace: %+v", err) + + record1 := &types.Record{ + NamespaceID: ns1.ID, + ModuleID: module1.ID, + } + + record2 := &types.Record{ + NamespaceID: ns1.ID, + ModuleID: module1.ID, + Values: types.RecordValueSet{ + &types.RecordValue{ + Name: "name", + Value: "John Doe", + }, + &types.RecordValue{ + Name: "email", + Value: "john.doe@example.com", + }, + &types.RecordValue{ + Name: "options", + Value: "1", + }, + &types.RecordValue{ + Name: "options", + Value: "2", + }, + &types.RecordValue{ + Name: "options", + Value: "3", + }, + &types.RecordValue{ + Name: "description", + Value: "just an example", + }, + &types.RecordValue{ + Name: "another_record", + Value: "918273645", + }, + }, + } + + { + // Let's put something to another namespace... + _, err := svc.Create(&types.Record{ + NamespaceID: ns2.ID, + ModuleID: module2.ID, + }) + test.Assert(t, err == nil, "Error when creating record: %+v", err) + } + + // now work with records + { + { + record1.UpdatedAt = nil + m, err := svc.Update(record1) + test.Assert(t, m == nil, "Expected empty return for invalid update, got %#v", m) + test.Assert(t, err != nil, "Expected error when updating invalid record") + } + + // create record + m1, err := svc.Create(record1) + test.Assert(t, err == nil, "Error when creating record: %+v", err) + test.Assert(t, m1.ID > 0, "Expected auto generated ID") + + // create record + m2, err := svc.Create(record2) + test.Assert(t, err == nil, "Error when creating record: %+v", err) + test.Assert(t, m2.ID > 0, "Expected auto generated ID") + + // fetch created record + { + ms, err := svc.FindByID(m1.NamespaceID, m1.ID) + test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) + test.Assert(t, ms.ID == m1.ID, "Expected ID from database to match, %d != %d", m1.ID, ms.ID) + test.Assert(t, ms.ModuleID == m1.ModuleID, "Expected Module ID from database to match, %d != %d", m1.ModuleID, ms.ModuleID) + } + + // update created record + { + m1.UpdatedAt = nil + _, err := svc.Update(m1) + test.Assert(t, err == nil, "Error when updating record, %+v", err) + } + + // re-fetch record + { + ms, err := svc.FindByID(m1.NamespaceID, m1.ID) + test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) + test.Assert(t, ms.ID == m1.ID, "Expected ID from database to match, %d != %d", m1.ID, ms.ID) + test.Assert(t, ms.ModuleID == m1.ModuleID, "Expected ID from database to match, %d != %d", m1.ModuleID, ms.ModuleID) + } + + // fetch all records + { + mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "id desc"}) + test.Assert(t, err == nil, "Error when retrieving records: %+v", err) + test.Assert(t, len(mr) == 2, "Expected two record, got %d", len(mr)) + test.Assert(t, f.Count == 2, "Expected Meta.Count == 2, got %d", f.Count) + test.Assert(t, f.Sort == "id desc", "Expected Meta.Sort == id desc, got '%s'", f.Sort) + test.Assert(t, mr[0].ModuleID == m1.ModuleID, "Expected record module1 to match, %d != %d", m1.ModuleID, mr[0].ModuleID) + test.Assert(t, mr[0].ID > mr[1].ID, "Expected order to be descending") + } + + // fetch all records + { + + mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "name asc, email desc"}) + test.Assert(t, err == nil, "Error when retrieving records: %+v", err) + test.Assert(t, len(mr) == 2, "Expected two record, got %d", len(mr)) + test.Assert(t, f.Count == 2, "Expected Meta.Count == 2, got %d", f.Count) + test.Assert(t, f.Sort == "name asc, email desc", "Expected Meta.Sort == 'name asc, email desc' '%s'", f.Sort) + test.Assert(t, mr[0].ModuleID == m1.ModuleID, "Expected record module1 to match, %d != %d", m1.ModuleID, mr[0].ModuleID) + + // @todo sort is not stable + // test.Assert(t, mr[0].ID > mr[1].ID, "Expected order to be ascending") + } + + // fetch all records + { + mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "created_at desc"}) + test.Assert(t, err == nil, "Error when retrieving records: %+v", err) + test.Assert(t, len(mr) == 2, "Expected two record, got %d", len(mr)) + test.Assert(t, f.Count == 2, "Expected Meta.Count == 2, got %d", f.Count) + test.Assert(t, f.Sort == "created_at desc", "Expected Meta.Sort == created_at desc, got '%s'", f.Sort) + test.Assert(t, mr[0].ModuleID == m1.ModuleID, "Expected record module1 to match, %d != %d", m1.ModuleID, mr[0].ModuleID) + + // @todo sort is not stable + // test.Assert(t, mr[0].ID > mr[1].ID, "Expected order to be ascending") + } + + // fetch all records by query + { + filter := "name='John Doe' AND email='john.doe@example.com'" + sort := "id desc" + + mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: sort, Filter: filter}) + test.Assert(t, err == nil, "Error when retrieving records: %+v", err) + test.Assert(t, len(mr) == 1, "Expected one record, got %d", len(mr)) + test.Assert(t, f.Count == 1, "Expected Meta.Count == 1, got %d", f.Count) + test.Assert(t, f.Page == 0, "Expected Meta.Page == 0, got %d", f.Page) + test.Assert(t, f.PerPage == 50, "Expected Meta.PerPage == 50, got %d", f.PerPage) + test.Assert(t, f.Filter == filter, "Expected Meta.Filter == %q, got %q", filter, f.Filter) + test.Assert(t, f.Sort == sort, "Expected Meta.Sort == %q, got %q", sort, f.Sort) + } + + // fetch all records by query + { + mr, _, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "id asc", Filter: "name='niall'"}) + test.Assert(t, err == nil, "Error when retrieving records: %+v", err) + test.Assert(t, len(mr) == 0, "Expected no records, got %d", len(mr)) + } + + // delete record + { + err := svc.DeleteByID(m1.NamespaceID, m1.ID) + test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) + + err = svc.DeleteByID(m2.NamespaceID, m2.ID) + test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) + } + + // fetch all records + { + mr, _, err := svc.Find(types.RecordFilter{ModuleID: module1.ID}) + test.Assert(t, err == nil, "Error when retrieving records: %+v", err) + test.Assert(t, len(mr) == 0, "Expected no record, got %d", len(mr)) + } + } +} diff --git a/compose/internal/service/record_test.go b/compose/internal/service/record_test.go index 39f49f95f..5f11d0980 100644 --- a/compose/internal/service/record_test.go +++ b/compose/internal/service/record_test.go @@ -1,257 +1,13 @@ -// +build integration - package service import ( - "context" "testing" - "github.com/titpetric/factory" - "github.com/cortezaproject/corteza-server/compose/types" - "github.com/cortezaproject/corteza-server/internal/auth" "github.com/cortezaproject/corteza-server/internal/permissions" "github.com/cortezaproject/corteza-server/internal/test" ) -func TestRecord(t *testing.T) { - factory.Database.MustGet("compose").Profiler = newTestLogProfiler(t) - - ctx := context.WithValue(context.Background(), "testing", true) - - ctx = auth.SetIdentityToContext(ctx, auth.NewIdentity(1337)) - - var err error - ns1, ns2 := createTestNamespaces(ctx, t) - - moduleSvc := Module().With(ctx) - svc := Record().With(ctx) - svc.(*record).ac = AccessControl(&permissions.ServiceAllowAll{}) - - module1 := &types.Module{ - NamespaceID: ns1.ID, - Name: "Test", - Fields: types.ModuleFieldSet{ - &types.ModuleField{ - Name: "name", - }, - &types.ModuleField{ - Name: "email", - }, - &types.ModuleField{ - Name: "options", - Multi: true, - }, - &types.ModuleField{ - Name: "description", - }, - &types.ModuleField{ - Name: "another_record", - Kind: "Record", - }, - }, - } - - // set up a module1 - module1, err = moduleSvc.Create(module1) - test.Assert(t, err == nil, "Error when creating module1: %+v", err) - test.Assert(t, module1.ID > 0, "Expected auto generated ID") - - module2 := &types.Module{ - NamespaceID: ns2.ID, - Name: "Test Dummy", - Fields: types.ModuleFieldSet{ - &types.ModuleField{ - Name: "name", - }, - &types.ModuleField{ - Name: "email", - }, - &types.ModuleField{ - Name: "options", - Multi: true, - }, - &types.ModuleField{ - Name: "description", - }, - &types.ModuleField{ - Name: "another_record", - Kind: "Record", - }, - }, - } - module2, err = moduleSvc.Create(module2) - test.Assert(t, err == nil, "Error when creating module1 in another namespace: %+v", err) - - record1 := &types.Record{ - NamespaceID: ns1.ID, - ModuleID: module1.ID, - } - - record2 := &types.Record{ - NamespaceID: ns1.ID, - ModuleID: module1.ID, - Values: types.RecordValueSet{ - &types.RecordValue{ - Name: "name", - Value: "John Doe", - }, - &types.RecordValue{ - Name: "email", - Value: "john.doe@example.com", - }, - &types.RecordValue{ - Name: "options", - Value: "1", - }, - &types.RecordValue{ - Name: "options", - Value: "2", - }, - &types.RecordValue{ - Name: "options", - Value: "3", - }, - &types.RecordValue{ - Name: "description", - Value: "just an example", - }, - &types.RecordValue{ - Name: "another_record", - Value: "918273645", - }, - }, - } - - { - // Let's put something to another namespace... - _, err := svc.Create(&types.Record{ - NamespaceID: ns2.ID, - ModuleID: module2.ID, - }) - test.Assert(t, err == nil, "Error when creating record: %+v", err) - } - - // now work with records - { - { - record1.UpdatedAt = nil - m, err := svc.Update(record1) - test.Assert(t, m == nil, "Expected empty return for invalid update, got %#v", m) - test.Assert(t, err != nil, "Expected error when updating invalid record") - } - - // create record - m1, err := svc.Create(record1) - test.Assert(t, err == nil, "Error when creating record: %+v", err) - test.Assert(t, m1.ID > 0, "Expected auto generated ID") - - // create record - m2, err := svc.Create(record2) - test.Assert(t, err == nil, "Error when creating record: %+v", err) - test.Assert(t, m2.ID > 0, "Expected auto generated ID") - - // fetch created record - { - ms, err := svc.FindByID(m1.NamespaceID, m1.ID) - test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) - test.Assert(t, ms.ID == m1.ID, "Expected ID from database to match, %d != %d", m1.ID, ms.ID) - test.Assert(t, ms.ModuleID == m1.ModuleID, "Expected Module ID from database to match, %d != %d", m1.ModuleID, ms.ModuleID) - } - - // update created record - { - m1.UpdatedAt = nil - _, err := svc.Update(m1) - test.Assert(t, err == nil, "Error when updating record, %+v", err) - } - - // re-fetch record - { - ms, err := svc.FindByID(m1.NamespaceID, m1.ID) - test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) - test.Assert(t, ms.ID == m1.ID, "Expected ID from database to match, %d != %d", m1.ID, ms.ID) - test.Assert(t, ms.ModuleID == m1.ModuleID, "Expected ID from database to match, %d != %d", m1.ModuleID, ms.ModuleID) - } - - // fetch all records - { - mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "id desc"}) - test.Assert(t, err == nil, "Error when retrieving records: %+v", err) - test.Assert(t, len(mr) == 2, "Expected two record, got %d", len(mr)) - test.Assert(t, f.Count == 2, "Expected Meta.Count == 2, got %d", f.Count) - test.Assert(t, f.Sort == "id desc", "Expected Meta.Sort == id desc, got '%s'", f.Sort) - test.Assert(t, mr[0].ModuleID == m1.ModuleID, "Expected record module1 to match, %d != %d", m1.ModuleID, mr[0].ModuleID) - test.Assert(t, mr[0].ID > mr[1].ID, "Expected order to be descending") - } - - // fetch all records - { - - mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "name asc, email desc"}) - test.Assert(t, err == nil, "Error when retrieving records: %+v", err) - test.Assert(t, len(mr) == 2, "Expected two record, got %d", len(mr)) - test.Assert(t, f.Count == 2, "Expected Meta.Count == 2, got %d", f.Count) - test.Assert(t, f.Sort == "name asc, email desc", "Expected Meta.Sort == 'name asc, email desc' '%s'", f.Sort) - test.Assert(t, mr[0].ModuleID == m1.ModuleID, "Expected record module1 to match, %d != %d", m1.ModuleID, mr[0].ModuleID) - - // @todo sort is not stable - // test.Assert(t, mr[0].ID > mr[1].ID, "Expected order to be ascending") - } - - // fetch all records - { - mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "created_at desc"}) - test.Assert(t, err == nil, "Error when retrieving records: %+v", err) - test.Assert(t, len(mr) == 2, "Expected two record, got %d", len(mr)) - test.Assert(t, f.Count == 2, "Expected Meta.Count == 2, got %d", f.Count) - test.Assert(t, f.Sort == "created_at desc", "Expected Meta.Sort == created_at desc, got '%s'", f.Sort) - test.Assert(t, mr[0].ModuleID == m1.ModuleID, "Expected record module1 to match, %d != %d", m1.ModuleID, mr[0].ModuleID) - - // @todo sort is not stable - // test.Assert(t, mr[0].ID > mr[1].ID, "Expected order to be ascending") - } - - // fetch all records by query - { - filter := "name='John Doe' AND email='john.doe@example.com'" - sort := "id desc" - - mr, f, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: sort, Filter: filter}) - test.Assert(t, err == nil, "Error when retrieving records: %+v", err) - test.Assert(t, len(mr) == 1, "Expected one record, got %d", len(mr)) - test.Assert(t, f.Count == 1, "Expected Meta.Count == 1, got %d", f.Count) - test.Assert(t, f.Page == 0, "Expected Meta.Page == 0, got %d", f.Page) - test.Assert(t, f.PerPage == 50, "Expected Meta.PerPage == 50, got %d", f.PerPage) - test.Assert(t, f.Filter == filter, "Expected Meta.Filter == %q, got %q", filter, f.Filter) - test.Assert(t, f.Sort == sort, "Expected Meta.Sort == %q, got %q", sort, f.Sort) - } - - // fetch all records by query - { - mr, _, err := svc.Find(types.RecordFilter{ModuleID: module1.ID, Sort: "id asc", Filter: "name='niall'"}) - test.Assert(t, err == nil, "Error when retrieving records: %+v", err) - test.Assert(t, len(mr) == 0, "Expected no records, got %d", len(mr)) - } - - // delete record - { - err := svc.DeleteByID(m1.NamespaceID, m1.ID) - test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) - - err = svc.DeleteByID(m2.NamespaceID, m2.ID) - test.Assert(t, err == nil, "Error when retrieving record by id: %+v", err) - } - - // fetch all records - { - mr, _, err := svc.Find(types.RecordFilter{ModuleID: module1.ID}) - test.Assert(t, err == nil, "Error when retrieving records: %+v", err) - test.Assert(t, len(mr) == 0, "Expected no record, got %d", len(mr)) - } - } -} - func TestValueSanitizer(t *testing.T) { var ( svc = record{ @@ -265,36 +21,50 @@ func TestValueSanitizer(t *testing.T) { &types.ModuleField{Name: "multiRef1", Kind: "Record", Multi: true}, }, } - rvs types.RecordValueSet + + rvs, out types.RecordValueSet + err error ) rvs = types.RecordValueSet{{Name: "single1", Value: "single"}} - test.NoError(t, svc.sanitizeValues(module, rvs), "unexpected error for sanitizeValues() call: %v") - test.Assert(t, len(rvs) == 1, "expecting 1 record value after sanitization, got %d", len(rvs)) + out, err = svc.sanitizeValues(module, rvs) + test.NoError(t, err, "unexpected error for sanitizeValues() call: %v") + test.Assert(t, len(out) == 1, "expecting 1 record value after sanitization, got %d", len(rvs)) rvs = types.RecordValueSet{{Name: "unknown", Value: "single"}} - test.Assert(t, svc.sanitizeValues(module, rvs) != nil, "expecting sanitizeValues() to return an error, got nil") + out, err = svc.sanitizeValues(module, rvs) + test.Assert(t, err != nil, "expecting sanitizeValues() to return an error, got nil") rvs = types.RecordValueSet{{Name: "single1", Value: "single"}, {Name: "single1", Value: "single2"}} - test.Assert(t, svc.sanitizeValues(module, rvs) != nil, "expecting sanitizeValues() to return an error, got nil") + out, err = svc.sanitizeValues(module, rvs) + test.Assert(t, err != nil, "expecting sanitizeValues() to return an error, got nil") rvs = types.RecordValueSet{{Name: "multi1", Value: "multi1"}, {Name: "multi1", Value: "multi1"}} - test.NoError(t, svc.sanitizeValues(module, rvs), "unexpected error for sanitizeValues() call: %v") - test.Assert(t, len(rvs) == 2, "expecting 2 record values after sanitization, got %d", len(rvs)) - test.Assert(t, rvs[0].Place == 0, "expecting first value to have place value 0, got %d", rvs[0].Place) - test.Assert(t, rvs[1].Place == 1, "expecting second value to have place value 1, got %d", rvs[1].Place) + out, err = svc.sanitizeValues(module, rvs) + test.NoError(t, err, "unexpected error for sanitizeValues() call: %v") + test.Assert(t, len(out) == 2, "expecting 2 record values after sanitization, got %d", len(rvs)) + test.Assert(t, out[0].Place == 0, "expecting first value to have place value 0, got %d", out[0].Place) + test.Assert(t, out[1].Place == 1, "expecting second value to have place value 1, got %d", out[1].Place) rvs = types.RecordValueSet{{Name: "ref1", Value: "multi1"}} - test.Assert(t, svc.sanitizeValues(module, rvs) != nil, "expecting sanitizeValues() to return an error, got nil") + out, err = svc.sanitizeValues(module, rvs) + test.Assert(t, err != nil, "expecting sanitizeValues() to return an error, got nil") rvs = types.RecordValueSet{{Name: "ref1", Value: "12345"}} - test.NoError(t, svc.sanitizeValues(module, rvs), "unexpected error for sanitizeValues() call: %v") - test.Assert(t, len(rvs) == 1, "expecting 1 record values after sanitization, got %d", len(rvs)) - test.Assert(t, rvs[0].Ref == 12345, "expecting parsed ref value to match, got %d", rvs[0].Ref) + out, err = svc.sanitizeValues(module, rvs) + test.NoError(t, err, "unexpected error for sanitizeValues() call: %v") + test.Assert(t, len(out) == 1, "expecting 1 record values after sanitization, got %d", len(rvs)) + test.Assert(t, out[0].Ref == 12345, "expecting parsed ref value to match, got %d", rvs[0].Ref) rvs = types.RecordValueSet{{Name: "multiRef1", Value: "12345"}, {Name: "multiRef1", Value: "67890"}} - test.NoError(t, svc.sanitizeValues(module, rvs), "unexpected error for sanitizeValues() call: %v") + out, err = svc.sanitizeValues(module, rvs) + test.NoError(t, err, "unexpected error for sanitizeValues() call: %v") test.Assert(t, len(rvs) == 2, "expecting 2 record values after sanitization, got %d", len(rvs)) - test.Assert(t, rvs[0].Ref == 12345, "expecting parsed ref value to match, got %d", rvs[0].Ref) - test.Assert(t, rvs[1].Ref == 67890, "expecting parsed ref value to match, got %d", rvs[1].Ref) + test.Assert(t, out[0].Ref == 12345, "expecting parsed ref value to match, got %d", out[0].Ref) + test.Assert(t, out[1].Ref == 67890, "expecting parsed ref value to match, got %d", out[1].Ref) + + rvs = types.RecordValueSet{{Name: "ref1", Value: ""}} + out, err = svc.sanitizeValues(module, rvs) + test.NoError(t, err, "unexpected error for sanitizeValues() call: %v") + test.Assert(t, len(out) == 0, "expecting 0 record values after sanitization, got %d", len(rvs)) }