| // 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() |
| } |
| } |