blob: 0e8b3c5b1a2d9cdbd3332ca2339b72205d150385 [file] [log] [blame]
// 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)
}
}
}