ducky/devices
ducky/devices/storer_test.go
Add ToMap and ToSlice helpers. Add helper functions that convert a map of ID-keyed Devices into a slice, and back. We'll use these a lot (especially with GetMany) as shorthand helper functions.
1 package devices
3 import (
4 "testing"
5 "time"
7 "code.secondbit.org/uuid.hg"
8 "golang.org/x/net/context"
9 )
11 var storers []Storer
13 func compareDevices(device1, device2 Device) (ok bool, field string, expected, result interface{}) {
14 if !device1.ID.Equal(device2.ID) {
15 return false, "ID", device1.ID, device2.ID
16 }
17 if device1.Name != device2.Name {
18 return false, "Name", device1.Name, device2.Name
19 }
20 if !device1.Owner.Equal(device2.Owner) {
21 return false, "Owner", device1.Owner, device2.Owner
22 }
23 if device1.Type != device2.Type {
24 return false, "Type", device1.Type, device2.Type
25 }
26 if !device1.Created.Equal(device2.Created) {
27 return false, "Created", device1.Created, device2.Created
28 }
29 if !device1.LastSeen.Equal(device2.LastSeen) {
30 return false, "LastSeen", device1.LastSeen, device2.LastSeen
31 }
32 if device1.PushToken != device2.PushToken {
33 return false, "PushToken", device1.PushToken, device2.PushToken
34 }
35 return true, "", nil, nil
36 }
38 func TestCreateAndGetDevices(t *testing.T) {
39 for _, storer := range storers {
40 storer, err := storer.Factory(context.TODO())
41 if err != nil {
42 t.Fatalf("Fatal error creating %T: %+v\n", storer, err)
43 }
45 devices := []Device{
46 {ID: uuid.NewID(), Name: "Test 1", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
47 {ID: uuid.NewID(), Name: "Test 2", Owner: uuid.NewID(), Type: TypeAndroidTablet, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
48 {ID: uuid.NewID(), Name: "Test 3", Owner: uuid.NewID(), Type: TypeChromeExtension, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
49 }
51 err = storer.CreateDevices(devices, context.TODO())
52 if err != nil {
53 t.Errorf("Error creating devices in %T: %+v\n", storer, err)
54 }
56 ids := make([]uuid.ID, 0, len(devices))
57 for _, device := range devices {
58 ids = append(ids, device.ID)
59 }
61 results, err := storer.GetDevices(ids, context.TODO())
62 if err != nil {
63 t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
64 }
65 for _, device := range devices {
66 d, returned := results[device.ID.String()]
67 if !returned {
68 t.Errorf("Expected device %s to be in results from %T, but wasn't present\n", device.Name, storer)
69 }
70 ok, field, expected, result := compareDevices(device, d)
71 if !ok {
72 t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, device.Name, expected, result, storer)
73 }
74 }
75 err = storer.Destroy(context.TODO())
76 if err != nil {
77 t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
78 }
79 }
80 }
82 func TestGetDevicesNoErrorForMissing(t *testing.T) {
83 for _, storer := range storers {
84 storer, err := storer.Factory(context.TODO())
85 if err != nil {
86 t.Fatalf("Fatal error creatng %T: %+v\n", storer, err)
87 }
89 results, err := storer.GetDevices([]uuid.ID{uuid.NewID()}, context.TODO())
90 if err != nil {
91 t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
92 }
93 if len(results) != 0 {
94 t.Errorf("Expected results to be empty, got %+v from %T instead\n", results, storer)
95 }
96 err = storer.Destroy(context.TODO())
97 if err != nil {
98 t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
99 }
100 }
101 }
103 func TestCreateDevicesDuplicates(t *testing.T) {
104 for _, storer := range storers {
105 storer, err := storer.Factory(context.TODO())
106 if err != nil {
107 t.Fatalf("Fatal error creating %T: %+v\n", storer, err)
108 }
110 devices := []Device{
111 {ID: uuid.NewID(), Name: "Test 1", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
112 {ID: uuid.NewID(), Name: "Test 2", Owner: uuid.NewID(), Type: TypeAndroidTablet, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
113 {ID: uuid.NewID(), Name: "Test 3", Owner: uuid.NewID(), Type: TypeChromeExtension, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
114 }
116 err = storer.CreateDevices(devices, context.TODO())
117 if err != nil {
118 t.Errorf("Unexpected error creating devices in %T: %+v\n", storer, err)
119 }
121 newDevices := []Device{
122 {ID: uuid.NewID(), Name: "Test 4", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
123 {ID: uuid.NewID(), Name: "Test 5", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
124 }
126 err = storer.CreateDevices([]Device{newDevices[0], devices[1], newDevices[1]}, context.TODO())
127 daeErr, ok := err.(ErrDeviceAlreadyExists)
128 if !ok {
129 t.Errorf("Expected ErrDeviceAlreadyExists creating duplicate device in %T, got %+v\n", storer, err)
130 }
131 if !uuid.ID(daeErr).Equal(devices[1].ID) {
132 t.Errorf("Expected ErrDeviceAlreadyExists to be %+v, got %+v from %T\n", devices[1].ID, daeErr, storer)
133 }
135 // inserts should be a transaction; they either all make it, or none do
136 results, err := storer.GetDevices([]uuid.ID{newDevices[0].ID, newDevices[1].ID}, context.TODO())
137 if err != nil {
138 t.Errorf("Error retrieving devices from %T: %+v\n", storer, err)
139 }
140 if len(results) != 0 {
141 t.Errorf("Expected new inserts to not be in results, got %+v from %T\n", results, storer)
142 }
144 err = storer.Destroy(context.TODO())
145 if err != nil {
146 t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
147 }
148 }
149 }