blob: 7e8a03038ff8d1e9aabdf63306c41df23f5240aa [file] [edit]
// Copyright 2024 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
//
// https://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.
package manager
import (
"context"
"path/filepath"
"slices"
"testing"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/testing/protocmp"
pcpb "github.com/GoogleCloudPlatform/google-guest-agent/pkg/proto/plugin_comm"
)
func TestInitWatcher(t *testing.T) {
w, err := InitWatcher(context.Background(), "pluginA", 100, "initialized")
if err != nil {
t.Fatalf("InitWatcher(ctx, pluginA, 100, initialized) failed unexpectedly with error: %v", err)
}
if !slices.Equal(w.Events(), []string{EventID}) {
t.Errorf("watcher.Events = %v, want %v", w.Events(), []string{EventID})
}
if w.ID() != WatcherID {
t.Errorf("watcher.ID = %s, want %s", w.ID(), WatcherID)
}
}
func TestWatcher(t *testing.T) {
ctx := context.Background()
addr := filepath.Join(t.TempDir(), "pluginA_revisionA.sock")
startTestServer(t, &testPluginServer{code: 100}, "unix", addr)
p := &Plugin{Name: "pluginA", Revision: "revisionA", Address: addr, Protocol: udsProtocol}
if err := p.Connect(ctx); err != nil {
t.Fatalf("p.Connect(ctx) failed unexpectedly with error: %v", err)
}
orig := pluginManager
t.Cleanup(func() { pluginManager = orig })
pluginManager = &PluginManager{plugins: map[string]*Plugin{"pluginA": p}, pluginMonitors: make(map[string]string)}
tests := []struct {
name string
plugin string
request string
wantStatus *pcpb.Status
wantRun bool
wantErr bool
}{
{
name: "unknown_plugin",
plugin: "pluginB",
wantRun: false,
wantErr: true,
},
{
name: "valid_plugin_success",
plugin: "pluginA",
request: "early-initialized",
wantRun: false,
wantErr: false,
wantStatus: &pcpb.Status{Code: 100, Results: []string{"initialized"}},
},
{
name: "valid_plugin_rpc_error",
plugin: "pluginA",
request: "fail",
wantRun: true,
wantErr: true,
},
{
name: "valid_plugin_status_mismatch",
plugin: "pluginA",
request: "some-other-request",
wantRun: true,
wantErr: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
watcher := &Watcher{name: test.plugin, statusCode: 100, request: test.request}
gotRun, data, err := watcher.Run(ctx, EventID)
if gotRun != test.wantRun {
t.Errorf("watcher.Run(ctx, %s) = continue running %t, want %t", EventID, gotRun, test.wantRun)
}
if (err != nil) != test.wantErr {
t.Errorf("watcher.Run(ctx, %s) = error %v, want error %t", EventID, err, test.wantErr)
}
if test.wantStatus == nil {
if data != nil {
t.Fatalf("watcher.Run(ctx, %s) = data %+v, want nil", EventID, data)
}
return
}
gotStatus, ok := data.(*pcpb.Status)
if !ok {
t.Fatalf("watcher.Run(ctx, %s) = data type %T, want *pcpb.Status", EventID, data)
}
if diff := cmp.Diff(test.wantStatus, gotStatus, protocmp.Transform()); diff != "" {
t.Errorf("watcher.Run(ctx, %s) = data diff (-want +got):\n%s", EventID, diff)
}
})
}
}