ducky/devices

Paddy 2015-11-20 Parent:34130c700842 Child:74dbc04879a7

9:f5a9d5f8f28d Go to Latest

ducky/devices/storer_test.go

Separate out StorerFactory into its own interface. We had previously included a Factory and Destroy method in the Storer interface, but it makes more sense to separate those out into a StorerFactory interface. This lets us avoid the impression that we're using the same instance of a Storer for every test, separates the test methods away from the methods that are actually used in prod, and hides them from Godoc. What's not to like?

History
paddy@2 1 package devices
paddy@2 2
paddy@2 3 import (
paddy@2 4 "testing"
paddy@2 5 "time"
paddy@2 6
paddy@2 7 "code.secondbit.org/uuid.hg"
paddy@2 8 "golang.org/x/net/context"
paddy@2 9 )
paddy@2 10
paddy@9 11 type StorerFactory interface {
paddy@9 12 NewStorer(ctx context.Context) (Storer, error)
paddy@9 13 TeardownStorer(storer Storer, ctx context.Context) error
paddy@9 14 }
paddy@9 15
paddy@9 16 var storerFactories []StorerFactory
paddy@2 17
paddy@2 18 func compareDevices(device1, device2 Device) (ok bool, field string, expected, result interface{}) {
paddy@2 19 if !device1.ID.Equal(device2.ID) {
paddy@2 20 return false, "ID", device1.ID, device2.ID
paddy@2 21 }
paddy@2 22 if device1.Name != device2.Name {
paddy@2 23 return false, "Name", device1.Name, device2.Name
paddy@2 24 }
paddy@2 25 if !device1.Owner.Equal(device2.Owner) {
paddy@2 26 return false, "Owner", device1.Owner, device2.Owner
paddy@2 27 }
paddy@2 28 if device1.Type != device2.Type {
paddy@2 29 return false, "Type", device1.Type, device2.Type
paddy@2 30 }
paddy@2 31 if !device1.Created.Equal(device2.Created) {
paddy@2 32 return false, "Created", device1.Created, device2.Created
paddy@2 33 }
paddy@2 34 if !device1.LastSeen.Equal(device2.LastSeen) {
paddy@2 35 return false, "LastSeen", device1.LastSeen, device2.LastSeen
paddy@2 36 }
paddy@2 37 if device1.PushToken != device2.PushToken {
paddy@2 38 return false, "PushToken", device1.PushToken, device2.PushToken
paddy@2 39 }
paddy@2 40 return true, "", nil, nil
paddy@2 41 }
paddy@2 42
paddy@5 43 func TestCreateAndGetDevices(t *testing.T) {
paddy@9 44 for _, factory := range storerFactories {
paddy@9 45 storer, err := factory.NewStorer(context.TODO())
paddy@2 46 if err != nil {
paddy@9 47 t.Fatalf("Fatal error creating Storer from %T: %+v\n", factory, err)
paddy@2 48 }
paddy@2 49
paddy@2 50 devices := []Device{
paddy@2 51 {ID: uuid.NewID(), Name: "Test 1", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@2 52 {ID: uuid.NewID(), Name: "Test 2", Owner: uuid.NewID(), Type: TypeAndroidTablet, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@2 53 {ID: uuid.NewID(), Name: "Test 3", Owner: uuid.NewID(), Type: TypeChromeExtension, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@2 54 }
paddy@3 55
paddy@3 56 err = storer.CreateDevices(devices, context.TODO())
paddy@3 57 if err != nil {
paddy@5 58 t.Errorf("Error creating devices in %T: %+v\n", storer, err)
paddy@3 59 }
paddy@3 60
paddy@2 61 ids := make([]uuid.ID, 0, len(devices))
paddy@2 62 for _, device := range devices {
paddy@2 63 ids = append(ids, device.ID)
paddy@2 64 }
paddy@2 65
paddy@2 66 results, err := storer.GetDevices(ids, context.TODO())
paddy@2 67 if err != nil {
paddy@2 68 t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
paddy@2 69 }
paddy@2 70 for _, device := range devices {
paddy@2 71 d, returned := results[device.ID.String()]
paddy@2 72 if !returned {
paddy@2 73 t.Errorf("Expected device %s to be in results from %T, but wasn't present\n", device.Name, storer)
paddy@2 74 }
paddy@2 75 ok, field, expected, result := compareDevices(device, d)
paddy@2 76 if !ok {
paddy@2 77 t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, device.Name, expected, result, storer)
paddy@2 78 }
paddy@2 79 }
paddy@9 80 err = factory.TeardownStorer(storer, context.TODO())
paddy@2 81 if err != nil {
paddy@2 82 t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
paddy@2 83 }
paddy@2 84 }
paddy@2 85 }
paddy@5 86
paddy@5 87 func TestGetDevicesNoErrorForMissing(t *testing.T) {
paddy@9 88 for _, factory := range storerFactories {
paddy@9 89 storer, err := factory.NewStorer(context.TODO())
paddy@5 90 if err != nil {
paddy@9 91 t.Fatalf("Fatal error creatng Storer from %T: %+v\n", factory, err)
paddy@5 92 }
paddy@5 93
paddy@5 94 results, err := storer.GetDevices([]uuid.ID{uuid.NewID()}, context.TODO())
paddy@5 95 if err != nil {
paddy@5 96 t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
paddy@5 97 }
paddy@5 98 if len(results) != 0 {
paddy@5 99 t.Errorf("Expected results to be empty, got %+v from %T instead\n", results, storer)
paddy@5 100 }
paddy@9 101 err = factory.TeardownStorer(storer, context.TODO())
paddy@5 102 if err != nil {
paddy@5 103 t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
paddy@5 104 }
paddy@5 105 }
paddy@5 106 }
paddy@5 107
paddy@5 108 func TestCreateDevicesDuplicates(t *testing.T) {
paddy@9 109 for _, factory := range storerFactories {
paddy@9 110 storer, err := factory.NewStorer(context.TODO())
paddy@5 111 if err != nil {
paddy@9 112 t.Fatalf("Fatal error creating Storer from %T: %+v\n", factory, err)
paddy@5 113 }
paddy@5 114
paddy@5 115 devices := []Device{
paddy@5 116 {ID: uuid.NewID(), Name: "Test 1", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@5 117 {ID: uuid.NewID(), Name: "Test 2", Owner: uuid.NewID(), Type: TypeAndroidTablet, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@5 118 {ID: uuid.NewID(), Name: "Test 3", Owner: uuid.NewID(), Type: TypeChromeExtension, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@5 119 }
paddy@5 120
paddy@5 121 err = storer.CreateDevices(devices, context.TODO())
paddy@5 122 if err != nil {
paddy@5 123 t.Errorf("Unexpected error creating devices in %T: %+v\n", storer, err)
paddy@5 124 }
paddy@5 125
paddy@5 126 newDevices := []Device{
paddy@5 127 {ID: uuid.NewID(), Name: "Test 4", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@5 128 {ID: uuid.NewID(), Name: "Test 5", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@5 129 }
paddy@5 130
paddy@5 131 err = storer.CreateDevices([]Device{newDevices[0], devices[1], newDevices[1]}, context.TODO())
paddy@5 132 daeErr, ok := err.(ErrDeviceAlreadyExists)
paddy@5 133 if !ok {
paddy@5 134 t.Errorf("Expected ErrDeviceAlreadyExists creating duplicate device in %T, got %+v\n", storer, err)
paddy@5 135 }
paddy@5 136 if !uuid.ID(daeErr).Equal(devices[1].ID) {
paddy@5 137 t.Errorf("Expected ErrDeviceAlreadyExists to be %+v, got %+v from %T\n", devices[1].ID, daeErr, storer)
paddy@5 138 }
paddy@5 139
paddy@5 140 // inserts should be a transaction; they either all make it, or none do
paddy@5 141 results, err := storer.GetDevices([]uuid.ID{newDevices[0].ID, newDevices[1].ID}, context.TODO())
paddy@5 142 if err != nil {
paddy@5 143 t.Errorf("Error retrieving devices from %T: %+v\n", storer, err)
paddy@5 144 }
paddy@5 145 if len(results) != 0 {
paddy@5 146 t.Errorf("Expected new inserts to not be in results, got %+v from %T\n", results, storer)
paddy@5 147 }
paddy@5 148
paddy@9 149 err = factory.TeardownStorer(storer, context.TODO())
paddy@5 150 if err != nil {
paddy@5 151 t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
paddy@5 152 }
paddy@5 153 }
paddy@5 154 }
paddy@8 155
paddy@8 156 func TestCreateAndListDevicesByOwner(t *testing.T) {
paddy@9 157 for _, factory := range storerFactories {
paddy@9 158 storer, err := factory.NewStorer(context.TODO())
paddy@8 159 if err != nil {
paddy@9 160 t.Fatalf("Fatal error creating Storer from %T: %+v\n", factory, err)
paddy@8 161 }
paddy@8 162
paddy@8 163 owner1, owner2 := uuid.NewID(), uuid.NewID()
paddy@8 164 devices := []Device{
paddy@8 165 {ID: uuid.NewID(), Name: "Test 1", Owner: owner1, Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@8 166 {ID: uuid.NewID(), Name: "Test 2", Owner: owner2, Type: TypeAndroidTablet, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
paddy@8 167 {ID: uuid.NewID(), Name: "Test 3", Owner: owner1, Type: TypeChromeExtension, Created: time.Now().Add(time.Minute), LastSeen: time.Now(), PushToken: "test token"},
paddy@8 168 }
paddy@8 169
paddy@8 170 err = storer.CreateDevices(devices, context.TODO())
paddy@8 171 if err != nil {
paddy@8 172 t.Errorf("Error creating devices in %T: %+v\n", storer, err)
paddy@8 173 }
paddy@8 174
paddy@8 175 results, err := storer.ListDevicesByOwner(owner1, context.TODO())
paddy@8 176 if err != nil {
paddy@8 177 t.Errorf("Error listing devices for owner1 from %T: %+v\n", storer, err)
paddy@8 178 }
paddy@8 179 if len(results) != 2 {
paddy@8 180 t.Errorf("Expected %d results for owner1, got %d from %T\n", 2, len(results), storer)
paddy@8 181 }
paddy@8 182 resultMap := ToMap(results)
paddy@8 183 d, ok := resultMap[devices[0].ID.String()]
paddy@8 184 if !ok {
paddy@8 185 t.Errorf("Expected to get %s in results, got %+v from %T\n", devices[0].Name, results, storer)
paddy@8 186 }
paddy@8 187 ok, field, expected, result := compareDevices(devices[0], d)
paddy@8 188 if !ok {
paddy@8 189 t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, devices[0].Name, expected, result, storer)
paddy@8 190 }
paddy@8 191 d, ok = resultMap[devices[2].ID.String()]
paddy@8 192 if !ok {
paddy@8 193 t.Errorf("Expected to get %s in results, got %+v from %T\n", devices[2].Name, results, storer)
paddy@8 194 }
paddy@8 195 ok, field, expected, result = compareDevices(devices[2], d)
paddy@8 196 if !ok {
paddy@8 197 t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, devices[2].Name, expected, result, storer)
paddy@8 198 }
paddy@8 199
paddy@8 200 results, err = storer.ListDevicesByOwner(owner2, context.TODO())
paddy@8 201 if err != nil {
paddy@8 202 t.Errorf("Error listing devices for owner2 from %T: %+v\n", storer, err)
paddy@8 203 }
paddy@8 204 if len(results) != 1 {
paddy@8 205 t.Errorf("Expected %d results for owner2, got %d from %T\n", 1, len(results), storer)
paddy@8 206 }
paddy@8 207 ok, field, expected, result = compareDevices(devices[1], results[0])
paddy@8 208 if !ok {
paddy@8 209 t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, devices[1].Name, expected, result, storer)
paddy@8 210 }
paddy@8 211
paddy@9 212 err = factory.TeardownStorer(storer, context.TODO())
paddy@8 213 if err != nil {
paddy@8 214 t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
paddy@8 215 }
paddy@8 216 }
paddy@8 217 }