ducky/devices

Paddy 2015-11-27 Parent:f5a9d5f8f28d Child:683050b4546b

10:74dbc04879a7 Go to Latest

ducky/devices/storer_test.go

Implement and test updating devices, and reuse contexts. Update all our tests to use the same context.Context instance within each test case, so static analysis about how we're passing contexts around dosn't get tripped up. Also, write a test that will check to make sure that our Storer implementations all actually update the Device correctly. We create every possible permutation of a DeviceChange, just to make sure they all work.

History
     1.1 --- a/storer_test.go	Fri Nov 20 01:14:58 2015 -0800
     1.2 +++ b/storer_test.go	Fri Nov 27 10:37:27 2015 -0800
     1.3 @@ -1,6 +1,7 @@
     1.4  package devices
     1.5  
     1.6  import (
     1.7 +	"fmt"
     1.8  	"testing"
     1.9  	"time"
    1.10  
    1.11 @@ -15,6 +16,16 @@
    1.12  
    1.13  var storerFactories []StorerFactory
    1.14  
    1.15 +const (
    1.16 +	changeName = 1 << iota
    1.17 +	changeOwner
    1.18 +	changeType
    1.19 +	changeCreated
    1.20 +	changeLastSeen
    1.21 +	changePushToken
    1.22 +	changeVariations
    1.23 +)
    1.24 +
    1.25  func compareDevices(device1, device2 Device) (ok bool, field string, expected, result interface{}) {
    1.26  	if !device1.ID.Equal(device2.ID) {
    1.27  		return false, "ID", device1.ID, device2.ID
    1.28 @@ -42,7 +53,8 @@
    1.29  
    1.30  func TestCreateAndGetDevices(t *testing.T) {
    1.31  	for _, factory := range storerFactories {
    1.32 -		storer, err := factory.NewStorer(context.TODO())
    1.33 +		ctx := context.Background()
    1.34 +		storer, err := factory.NewStorer(ctx)
    1.35  		if err != nil {
    1.36  			t.Fatalf("Fatal error creating Storer from %T: %+v\n", factory, err)
    1.37  		}
    1.38 @@ -53,7 +65,7 @@
    1.39  			{ID: uuid.NewID(), Name: "Test 3", Owner: uuid.NewID(), Type: TypeChromeExtension, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
    1.40  		}
    1.41  
    1.42 -		err = storer.CreateDevices(devices, context.TODO())
    1.43 +		err = storer.CreateDevices(devices, ctx)
    1.44  		if err != nil {
    1.45  			t.Errorf("Error creating devices in %T: %+v\n", storer, err)
    1.46  		}
    1.47 @@ -63,7 +75,7 @@
    1.48  			ids = append(ids, device.ID)
    1.49  		}
    1.50  
    1.51 -		results, err := storer.GetDevices(ids, context.TODO())
    1.52 +		results, err := storer.GetDevices(ids, ctx)
    1.53  		if err != nil {
    1.54  			t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
    1.55  		}
    1.56 @@ -77,7 +89,7 @@
    1.57  				t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, device.Name, expected, result, storer)
    1.58  			}
    1.59  		}
    1.60 -		err = factory.TeardownStorer(storer, context.TODO())
    1.61 +		err = factory.TeardownStorer(storer, ctx)
    1.62  		if err != nil {
    1.63  			t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
    1.64  		}
    1.65 @@ -86,19 +98,20 @@
    1.66  
    1.67  func TestGetDevicesNoErrorForMissing(t *testing.T) {
    1.68  	for _, factory := range storerFactories {
    1.69 -		storer, err := factory.NewStorer(context.TODO())
    1.70 +		ctx := context.Background()
    1.71 +		storer, err := factory.NewStorer(ctx)
    1.72  		if err != nil {
    1.73  			t.Fatalf("Fatal error creatng Storer from %T: %+v\n", factory, err)
    1.74  		}
    1.75  
    1.76 -		results, err := storer.GetDevices([]uuid.ID{uuid.NewID()}, context.TODO())
    1.77 +		results, err := storer.GetDevices([]uuid.ID{uuid.NewID()}, ctx)
    1.78  		if err != nil {
    1.79  			t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
    1.80  		}
    1.81  		if len(results) != 0 {
    1.82  			t.Errorf("Expected results to be empty, got %+v from %T instead\n", results, storer)
    1.83  		}
    1.84 -		err = factory.TeardownStorer(storer, context.TODO())
    1.85 +		err = factory.TeardownStorer(storer, ctx)
    1.86  		if err != nil {
    1.87  			t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
    1.88  		}
    1.89 @@ -107,7 +120,8 @@
    1.90  
    1.91  func TestCreateDevicesDuplicates(t *testing.T) {
    1.92  	for _, factory := range storerFactories {
    1.93 -		storer, err := factory.NewStorer(context.TODO())
    1.94 +		ctx := context.Background()
    1.95 +		storer, err := factory.NewStorer(ctx)
    1.96  		if err != nil {
    1.97  			t.Fatalf("Fatal error creating Storer from %T: %+v\n", factory, err)
    1.98  		}
    1.99 @@ -118,7 +132,7 @@
   1.100  			{ID: uuid.NewID(), Name: "Test 3", Owner: uuid.NewID(), Type: TypeChromeExtension, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
   1.101  		}
   1.102  
   1.103 -		err = storer.CreateDevices(devices, context.TODO())
   1.104 +		err = storer.CreateDevices(devices, ctx)
   1.105  		if err != nil {
   1.106  			t.Errorf("Unexpected error creating devices in %T: %+v\n", storer, err)
   1.107  		}
   1.108 @@ -128,7 +142,7 @@
   1.109  			{ID: uuid.NewID(), Name: "Test 5", Owner: uuid.NewID(), Type: TypeAndroidPhone, Created: time.Now(), LastSeen: time.Now(), PushToken: "test token"},
   1.110  		}
   1.111  
   1.112 -		err = storer.CreateDevices([]Device{newDevices[0], devices[1], newDevices[1]}, context.TODO())
   1.113 +		err = storer.CreateDevices([]Device{newDevices[0], devices[1], newDevices[1]}, ctx)
   1.114  		daeErr, ok := err.(ErrDeviceAlreadyExists)
   1.115  		if !ok {
   1.116  			t.Errorf("Expected ErrDeviceAlreadyExists creating duplicate device in %T, got %+v\n", storer, err)
   1.117 @@ -138,7 +152,7 @@
   1.118  		}
   1.119  
   1.120  		// inserts should be a transaction; they either all make it, or none do
   1.121 -		results, err := storer.GetDevices([]uuid.ID{newDevices[0].ID, newDevices[1].ID}, context.TODO())
   1.122 +		results, err := storer.GetDevices([]uuid.ID{newDevices[0].ID, newDevices[1].ID}, ctx)
   1.123  		if err != nil {
   1.124  			t.Errorf("Error retrieving devices from %T: %+v\n", storer, err)
   1.125  		}
   1.126 @@ -146,7 +160,7 @@
   1.127  			t.Errorf("Expected new inserts to not be in results, got %+v from %T\n", results, storer)
   1.128  		}
   1.129  
   1.130 -		err = factory.TeardownStorer(storer, context.TODO())
   1.131 +		err = factory.TeardownStorer(storer, ctx)
   1.132  		if err != nil {
   1.133  			t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
   1.134  		}
   1.135 @@ -155,7 +169,8 @@
   1.136  
   1.137  func TestCreateAndListDevicesByOwner(t *testing.T) {
   1.138  	for _, factory := range storerFactories {
   1.139 -		storer, err := factory.NewStorer(context.TODO())
   1.140 +		ctx := context.Background()
   1.141 +		storer, err := factory.NewStorer(ctx)
   1.142  		if err != nil {
   1.143  			t.Fatalf("Fatal error creating Storer from %T: %+v\n", factory, err)
   1.144  		}
   1.145 @@ -167,12 +182,12 @@
   1.146  			{ID: uuid.NewID(), Name: "Test 3", Owner: owner1, Type: TypeChromeExtension, Created: time.Now().Add(time.Minute), LastSeen: time.Now(), PushToken: "test token"},
   1.147  		}
   1.148  
   1.149 -		err = storer.CreateDevices(devices, context.TODO())
   1.150 +		err = storer.CreateDevices(devices, ctx)
   1.151  		if err != nil {
   1.152  			t.Errorf("Error creating devices in %T: %+v\n", storer, err)
   1.153  		}
   1.154  
   1.155 -		results, err := storer.ListDevicesByOwner(owner1, context.TODO())
   1.156 +		results, err := storer.ListDevicesByOwner(owner1, ctx)
   1.157  		if err != nil {
   1.158  			t.Errorf("Error listing devices for owner1 from %T: %+v\n", storer, err)
   1.159  		}
   1.160 @@ -197,7 +212,7 @@
   1.161  			t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, devices[2].Name, expected, result, storer)
   1.162  		}
   1.163  
   1.164 -		results, err = storer.ListDevicesByOwner(owner2, context.TODO())
   1.165 +		results, err = storer.ListDevicesByOwner(owner2, ctx)
   1.166  		if err != nil {
   1.167  			t.Errorf("Error listing devices for owner2 from %T: %+v\n", storer, err)
   1.168  		}
   1.169 @@ -209,9 +224,106 @@
   1.170  			t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, devices[1].Name, expected, result, storer)
   1.171  		}
   1.172  
   1.173 -		err = factory.TeardownStorer(storer, context.TODO())
   1.174 +		err = factory.TeardownStorer(storer, ctx)
   1.175  		if err != nil {
   1.176  			t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
   1.177  		}
   1.178  	}
   1.179  }
   1.180 +
   1.181 +func TestUpdateDevicesHappyPath(t *testing.T) {
   1.182 +	device := Device{
   1.183 +		ID:        uuid.NewID(),
   1.184 +		Name:      "Test 1",
   1.185 +		Owner:     uuid.NewID(),
   1.186 +		Type:      TypeAndroidPhone,
   1.187 +		Created:   time.Now(),
   1.188 +		LastSeen:  time.Now(),
   1.189 +		PushToken: "test token",
   1.190 +	}
   1.191 +	for _, factory := range storerFactories {
   1.192 +		ctx := context.Background()
   1.193 +		storer, err := factory.NewStorer(ctx)
   1.194 +		if err != nil {
   1.195 +			t.Fatalf("Fatal error creating Storer from %T: %+v\n", factory, err)
   1.196 +		}
   1.197 +		for i := 1; i < changeVariations; i++ {
   1.198 +			var change DeviceChange
   1.199 +			var owner uuid.ID
   1.200 +			var name, pushToken string
   1.201 +			var created, lastSeen time.Time
   1.202 +			var deviceType DeviceType
   1.203 +
   1.204 +			device.ID = uuid.NewID()
   1.205 +
   1.206 +			expectation := device
   1.207 +			result := device
   1.208 +
   1.209 +			change.DeviceID = device.ID
   1.210 +
   1.211 +			if i&changeName != 0 {
   1.212 +				name = fmt.Sprintf("name-%d", i)
   1.213 +				change.Name = &name
   1.214 +				expectation.Name = name
   1.215 +			}
   1.216 +			if i&changeOwner != 0 {
   1.217 +				owner = uuid.NewID()
   1.218 +				change.Owner = &owner
   1.219 +				expectation.Owner = owner
   1.220 +			}
   1.221 +			if i&changeType != 0 {
   1.222 +				deviceType = DeviceType(fmt.Sprintf("type-%d", i))
   1.223 +				change.Type = &deviceType
   1.224 +				expectation.Type = deviceType
   1.225 +			}
   1.226 +			if i&changeCreated != 0 {
   1.227 +				created = time.Now().Add(time.Hour * time.Duration(i))
   1.228 +				change.Created = &created
   1.229 +				expectation.Created = created
   1.230 +			}
   1.231 +			if i&changeLastSeen != 0 {
   1.232 +				lastSeen = time.Now().Add(time.Minute * time.Duration(i*-1))
   1.233 +				change.LastSeen = &lastSeen
   1.234 +				expectation.LastSeen = lastSeen
   1.235 +			}
   1.236 +			if i&changePushToken != 0 {
   1.237 +				pushToken = fmt.Sprintf("push-token-%d", i)
   1.238 +				change.PushToken = &pushToken
   1.239 +				expectation.PushToken = pushToken
   1.240 +			}
   1.241 +			result = ApplyChange(result, change)
   1.242 +			ok, field, expectedVal, resultVal := compareDevices(expectation, result)
   1.243 +			if !ok {
   1.244 +				t.Errorf("Expected %s of %s to be %v, got %v after applying DeviceChange %+v\n", field, device.Name, expectedVal, resultVal, change)
   1.245 +			}
   1.246 +
   1.247 +			err = storer.CreateDevices([]Device{device}, ctx)
   1.248 +			if err != nil {
   1.249 +				t.Errorf("Unexpected error creating devices in %T: %+v\n", storer, err)
   1.250 +			}
   1.251 +
   1.252 +			err = storer.UpdateDevice(change, ctx)
   1.253 +			if err != nil {
   1.254 +				t.Errorf("Unexpected error updating device in %T: %+v\n", storer, err)
   1.255 +			}
   1.256 +
   1.257 +			retrieved, err := storer.GetDevices([]uuid.ID{device.ID}, ctx)
   1.258 +			if err != nil {
   1.259 +				t.Errorf("Unexpected error retrieving devices from %T: %+v\n", storer, err)
   1.260 +			}
   1.261 +			retrievedDevice, ok := retrieved[device.ID.String()]
   1.262 +			if !ok {
   1.263 +				t.Errorf("Expected retrieved devices to contain %s, got %+v from %T\n", device.Name, retrieved, storer)
   1.264 +			}
   1.265 +			ok, field, expectedVal, resultVal = compareDevices(expectation, retrievedDevice)
   1.266 +			if !ok {
   1.267 +				t.Errorf("Expected %s of %s to be %v, got %v from %T\n", field, device.Name, expectedVal, resultVal, storer)
   1.268 +			}
   1.269 +		}
   1.270 +
   1.271 +		err = factory.TeardownStorer(storer, ctx)
   1.272 +		if err != nil {
   1.273 +			t.Errorf("Error cleaning up after %T: %+v\n", storer, err)
   1.274 +		}
   1.275 +	}
   1.276 +}