blob: b7812a2022c401dde99acaf838753855eb8c5748 [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.
//go:build stackdriver_alpha
// +build stackdriver_alpha
package policyenforcer
import (
"errors"
"policy_manager/mock/mockdevicepolicy"
"policy_manager/mock/mocksystemd"
"testing"
"policy_manager/policymanagerproto"
"github.com/golang/mock/gomock"
"github.com/golang/protobuf/proto"
)
// TestUpdateHealthMonitorState cheecks the update made to health monitor. It
// updates the status of logging and monitoring.
func TestUpdateHealthMonitorState(t *testing.T) {
tests := []struct {
name string
onDiskConfig *policymanagerproto.InstanceConfig
getConfigErr error
getStatusErr error
isLogging bool
isMonitoring bool
expectChangeLogging bool
expectChangeLoggingErr error
expectChangeMonitoring bool
expectChangeMonitoringErr error
expectErr bool
}{
{
name: "NoEnforcement",
onDiskConfig: &policymanagerproto.InstanceConfig{},
getConfigErr: nil,
getStatusErr: nil,
isLogging: true,
isMonitoring: true,
expectChangeLogging: false,
expectChangeLoggingErr: nil,
expectChangeMonitoring: false,
expectChangeMonitoringErr: nil,
expectErr: false,
},
{
name: "TurnOnLogging",
onDiskConfig: &policymanagerproto.InstanceConfig{
HealthMonitorConfig: &policymanagerproto.HealthMonitorConfig{
Enforced: proto.Bool(true),
LoggingEnabled: proto.Bool(true),
},
},
getConfigErr: nil,
getStatusErr: nil,
isLogging: false,
isMonitoring: false,
expectChangeLogging: true,
expectChangeLoggingErr: nil,
expectChangeMonitoring: false,
expectChangeMonitoringErr: nil,
expectErr: false,
},
{
name: "TurnOnMonitoringTurnOffLogging",
onDiskConfig: &policymanagerproto.InstanceConfig{
HealthMonitorConfig: &policymanagerproto.HealthMonitorConfig{
Enforced: proto.Bool(true),
MonitoringEnabled: proto.Bool(true),
},
},
getConfigErr: nil,
getStatusErr: nil,
isLogging: true,
isMonitoring: false,
expectChangeLogging: true,
expectChangeLoggingErr: nil,
expectChangeMonitoring: true,
expectChangeMonitoringErr: nil,
expectErr: false,
},
{
name: "NoDiskConfig",
onDiskConfig: nil,
getConfigErr: errors.New("error"),
getStatusErr: nil,
isLogging: false,
isMonitoring: false,
expectChangeLogging: false,
expectChangeLoggingErr: nil,
expectChangeMonitoring: false,
expectChangeMonitoringErr: nil,
expectErr: true,
},
{
name: "ErrorWhenTurnOnLoggingWontAffectMonitoring",
onDiskConfig: &policymanagerproto.InstanceConfig{
HealthMonitorConfig: &policymanagerproto.HealthMonitorConfig{
Enforced: proto.Bool(true),
LoggingEnabled: proto.Bool(true),
MonitoringEnabled: proto.Bool(true),
},
},
getConfigErr: nil,
getStatusErr: nil,
isLogging: false,
isMonitoring: false,
expectChangeLogging: true,
expectChangeLoggingErr: errors.New("error"),
expectChangeMonitoring: true,
expectChangeMonitoringErr: nil,
expectErr: true,
},
}
for _, test := range tests {
t.Logf("Running: %s", test.name)
mockCtrl := gomock.NewController(t)
mockSystemd := mocksystemd.NewMockSystemdClient(mockCtrl)
mockManager := mockdevicepolicy.NewMockManager(mockCtrl)
mockHealthMonitor := NewHealthMonitorNPD()
mockManager.EXPECT().GetInstanceConfig().Return(test.onDiskConfig, test.getConfigErr)
checkLogging := mockSystemd.EXPECT().IsUnitActiveRunning(mockHealthMonitor.LoggingService()).Return(test.isLogging, nil).AnyTimes()
checkMonitoring := mockSystemd.EXPECT().IsUnitActiveRunning(mockHealthMonitor.MonitoringService()).Return(test.isMonitoring, test.getStatusErr).AnyTimes()
if test.expectChangeLogging {
if test.isLogging {
mockSystemd.EXPECT().StopUnit(mockHealthMonitor.LoggingService()).Return(test.expectChangeLoggingErr).After(checkLogging)
} else {
mockSystemd.EXPECT().StartUnit(mockHealthMonitor.LoggingService()).Return(test.expectChangeLoggingErr).After(checkLogging)
}
}
if test.expectChangeMonitoring {
if test.isMonitoring {
mockSystemd.EXPECT().StopUnit(mockHealthMonitor.MonitoringService()).Return(test.expectChangeMonitoringErr).After(checkMonitoring)
} else {
mockSystemd.EXPECT().StartUnit(mockHealthMonitor.MonitoringService()).Return(test.expectChangeMonitoringErr).After(checkMonitoring)
}
}
client := NewPolicyEnforcer(mockSystemd, mockManager, mockHealthMonitor)
err := client.UpdateHealthMonitorState()
if err == nil && test.expectErr {
t.Errorf("Test %s passed, want error", test.name)
} else if err != nil && !test.expectErr {
t.Errorf("Test %s got unexpected error %v", test.name, err)
}
mockCtrl.Finish()
}
}
// TestGetHealthMonitorStatus tests the retrieval of health monitor data.
func TestGetHealthMonitorStatus(t *testing.T) {
tests := []struct {
name string
isLogging bool
checkLoggingErr error
isMonitoring bool
checkMonitoringErr error
expectedStatus *policymanagerproto.HealthMonitorStatus
expectErr bool
}{
{
name: "BothNotRunning",
isLogging: false,
checkLoggingErr: nil,
isMonitoring: false,
checkMonitoringErr: nil,
expectedStatus: &policymanagerproto.HealthMonitorStatus{
Logging: proto.Bool(false),
Monitoring: proto.Bool(false),
},
expectErr: false,
},
{
name: "BothRunning",
isLogging: true,
checkLoggingErr: nil,
isMonitoring: true,
checkMonitoringErr: nil,
expectedStatus: &policymanagerproto.HealthMonitorStatus{
Logging: proto.Bool(true),
Monitoring: proto.Bool(true),
},
expectErr: false,
},
{
name: "CheckLoggingServiceFailed",
isLogging: false,
checkLoggingErr: errors.New("error"),
isMonitoring: true,
checkMonitoringErr: nil,
expectedStatus: &policymanagerproto.HealthMonitorStatus{
Monitoring: proto.Bool(true),
},
expectErr: true,
},
{
name: "CheckMonitoringServiceFailed",
isLogging: true,
checkLoggingErr: nil,
isMonitoring: false,
checkMonitoringErr: errors.New("error"),
expectedStatus: &policymanagerproto.HealthMonitorStatus{
Logging: proto.Bool(true),
},
expectErr: true,
},
}
for _, test := range tests {
t.Logf("Running: %s", test.name)
mockCtrl := gomock.NewController(t)
mockSystemd := mocksystemd.NewMockSystemdClient(mockCtrl)
mockManager := mockdevicepolicy.NewMockManager(mockCtrl)
mockHealthMonitor := NewHealthMonitorNPD()
mockSystemd.EXPECT().IsUnitActiveRunning(mockHealthMonitor.LoggingService()).Return(test.isLogging, test.checkLoggingErr)
mockSystemd.EXPECT().IsUnitActiveRunning(mockHealthMonitor.MonitoringService()).Return(test.isMonitoring, test.checkMonitoringErr)
client := NewPolicyEnforcer(mockSystemd, mockManager, mockHealthMonitor)
status, err := client.GetHealthMonitorStatus()
if err == nil && test.expectErr {
t.Errorf("Test %s passed, want error", test.name)
} else if err != nil && !test.expectErr {
t.Errorf("Test %s got unexpected error %v", test.name, err)
} else if !proto.Equal(status, test.expectedStatus) {
t.Errorf("Test %s got %s, want %s",
test.name,
status.String(),
test.expectedStatus.String())
}
mockCtrl.Finish()
}
}