| // Copyright 2021 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Unit tests for the UpdateEngineClient implementation. |
| package dbus |
| |
| import ( |
| "errors" |
| "github.com/golang/protobuf/proto" |
| "policy_manager/policymanagerproto" |
| "reflect" |
| "testing" |
| |
| godbus "github.com/godbus/dbus" |
| ) |
| |
| func newFakeUpdateEngineClient(fakeConn Conn) UpdateEngineClient { |
| return &updateEngineClientImpl{fakeConn} |
| } |
| |
| // TestSetChannel tests SetChannel calls dbus method as expected. |
| func TestSetChannel(t *testing.T) { |
| tests := []struct { |
| name string |
| targetChannel string |
| expectError bool |
| }{ |
| { |
| "NormalCase", |
| "foo-channel", |
| false, |
| }, |
| { |
| "ErrorCase", |
| "bar-channel", |
| true, |
| }, |
| } |
| |
| for _, test := range tests { |
| // Mock dbus connection and object. |
| fakeConn := NewFakeConn() |
| fakeObj := NewFakeBusObject() |
| fakeCall := func(args ...interface{}) ([]interface{}, error) { |
| if !test.expectError { |
| // Check arguments. |
| if len(args) != 2 || args[0] != test.targetChannel || args[1] != false { |
| return nil, errors.New("Check args failed.") |
| } |
| return nil, nil |
| } else { |
| return nil, errors.New("Expected error.") |
| } |
| } |
| fakeConn.SetObject(updateEngineObjectName, updateEngineObjectPath, fakeObj) |
| fakeObj.SetCall(setChannelMethod, fakeCall) |
| |
| ueClient := newFakeUpdateEngineClient(fakeConn) |
| err := ueClient.SetChannel(test.targetChannel) |
| |
| if err != nil && !test.expectError { |
| t.Errorf("Test %s got unexpected error: %v", test.name, err) |
| } else if err == nil && test.expectError { |
| t.Errorf("Test %s didn't get expected error", test.name) |
| } |
| } |
| } |
| |
| // TestAttemptUpdate tests AttemptUpdate calls dbus method as expected. |
| func TestAttemptUpdate(t *testing.T) { |
| tests := []struct { |
| name string |
| expectError bool |
| }{ |
| { |
| "NormalCase", |
| false, |
| }, |
| { |
| "ErrorCase", |
| true, |
| }, |
| } |
| |
| for _, test := range tests { |
| // Mock dbus connection and object. |
| fakeConn := NewFakeConn() |
| fakeObj := NewFakeBusObject() |
| fakeCall := func(args ...interface{}) ([]interface{}, error) { |
| if !test.expectError { |
| // Check arguments. |
| if len(args) != 2 || args[0] != "" || args[1] != "" { |
| return nil, errors.New("Check args failed.") |
| } |
| return nil, nil |
| } else { |
| return nil, errors.New("Expected error.") |
| } |
| } |
| fakeConn.SetObject(updateEngineObjectName, updateEngineObjectPath, fakeObj) |
| fakeObj.SetCall(attemptUpdateMethod, fakeCall) |
| |
| ueClient := newFakeUpdateEngineClient(fakeConn) |
| err := ueClient.AttemptUpdate() |
| |
| if err != nil && !test.expectError { |
| t.Errorf("Test %s got unexpected error %v", test.name, err) |
| } else if err == nil && test.expectError { |
| t.Errorf("Test %s didn't get expected error", test.name) |
| } |
| } |
| } |
| |
| // TestGetStatus tests GetStatus returns correct values. |
| func TestGetStatus(t *testing.T) { |
| rebootStatus := policymanagerproto.Operation_UPDATED_NEED_REBOOT |
| tests := []struct { |
| name string |
| expectedReturn *policymanagerproto.StatusResult |
| expectError bool |
| }{ |
| { |
| "NormalCase", |
| &policymanagerproto.StatusResult{ |
| NewVersion: proto.String("16550.0.0"), |
| UpdateStatus: &rebootStatus, |
| LastCheckedTime: proto.Int64(1433971203), |
| }, |
| false, |
| }, |
| { |
| "ErrorCase", |
| &policymanagerproto.StatusResult{ |
| NewVersion: proto.String("16550.0.0"), |
| UpdateStatus: nil, |
| LastCheckedTime: proto.Int64(1433971203), |
| }, |
| true, |
| }, |
| } |
| |
| for _, test := range tests { |
| // Mock dbus connection and object. |
| fakeConn := NewFakeConn() |
| fakeObj := NewFakeBusObject() |
| updateStatusBytes, err := proto.Marshal(test.expectedReturn) |
| if err != nil { |
| t.Errorf("Failed to marshal UpdateStatusBytes %v", updateStatusBytes) |
| } |
| fakeCall := func(args ...interface{}) ([]interface{}, error) { |
| if !test.expectError { |
| return []interface{}{ |
| updateStatusBytes, |
| }, nil |
| } else { |
| return nil, errors.New("Expected error.") |
| } |
| } |
| fakeConn.SetObject(updateEngineObjectName, updateEngineObjectPath, fakeObj) |
| fakeObj.SetCall(getStatusAdvancedMethod, fakeCall) |
| |
| ueClient := newFakeUpdateEngineClient(fakeConn) |
| ret, err := ueClient.GetStatus() |
| |
| if err == nil { |
| if test.expectError { |
| t.Errorf("Test %s didn't get expected error", test.name) |
| } else if !proto.Equal(test.expectedReturn, ret) { |
| t.Errorf("Test %s got unexpected return %v, want %v", test.name, ret, test.expectedReturn) |
| } |
| } else if !test.expectError { |
| t.Errorf("Test %s got unexpected error %v", test.name, err) |
| } |
| } |
| } |
| |
| // TestSubscribeStatusUpdate tests SubscribeStatusUpdate returns working channel |
| func TestSubscribeStatusUpdate(t *testing.T) { |
| tests := []struct { |
| name string |
| expectedReturn UEGetStatusResponse |
| expectError bool |
| }{ |
| { |
| "NormalCase", |
| UEGetStatusResponse{ |
| 1433971203, |
| 0.000000, |
| "UPDATE_STATUS_UPDATED_NEED_REBOOT", |
| "7150.0.0", |
| 66542575, |
| }, |
| false, |
| }, |
| { |
| "ErrorCase", |
| UEGetStatusResponse{}, |
| true, |
| }, |
| } |
| |
| for _, test := range tests { |
| // Mock dbus connection and object. |
| fakeConn := NewFakeConn() |
| fakeObj := NewFakeBusObject() |
| fakeCall := func(args ...interface{}) ([]interface{}, error) { |
| if test.expectError { |
| return nil, errors.New("Expected error.") |
| } else { |
| return nil, nil |
| } |
| } |
| fakeConn.SetBusObject(fakeObj) |
| fakeObj.SetCall(dBusAddMatchMethod, fakeCall) |
| |
| ueClient := newFakeUpdateEngineClient(fakeConn) |
| ch, err := ueClient.SubscribeStatusUpdate() |
| |
| if err == nil { |
| if test.expectError { |
| t.Errorf("Test %s didn't get expected error", test.name) |
| } else { |
| fakeConn.signal_channel <- &godbus.Signal{ |
| Body: []interface{}{ |
| test.expectedReturn.LastCheckedTime, |
| test.expectedReturn.Progress, |
| test.expectedReturn.UpdateStatus, |
| test.expectedReturn.NewVersion, |
| test.expectedReturn.NewSize, |
| }, |
| } |
| ret := <-ch |
| if !reflect.DeepEqual(test.expectedReturn, ret) { |
| t.Errorf("Test %s got unexpected return %v, want %v", test.name, ret, test.expectedReturn) |
| } |
| } |
| } else if !test.expectError { |
| t.Errorf("Test %s got unexpected error %v", test.name, err) |
| } |
| } |
| } |