github.com/vmware/govmomi@v0.51.0/simulator/event_manager_test.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package simulator
     6  
     7  import (
     8  	"context"
     9  	"reflect"
    10  	"testing"
    11  
    12  	"github.com/vmware/govmomi"
    13  	"github.com/vmware/govmomi/event"
    14  	"github.com/vmware/govmomi/vim25/types"
    15  )
    16  
    17  func TestEventManagerVPX(t *testing.T) {
    18  	logEvents = testing.Verbose()
    19  	ctx := context.Background()
    20  
    21  	m := VPX()
    22  	m.Datacenter = 2
    23  
    24  	defer m.Remove()
    25  
    26  	err := m.Create()
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	s := m.Service.NewServer()
    32  	defer s.Close()
    33  
    34  	c, err := govmomi.NewClient(ctx, s.URL, true)
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  
    39  	e := event.NewManager(c.Client)
    40  	count := m.Count()
    41  
    42  	root := c.ServiceContent.RootFolder
    43  	vm := m.Map().Any("VirtualMachine").(*VirtualMachine)
    44  	host := m.Map().Get(vm.Runtime.Host.Reference()).(*HostSystem)
    45  
    46  	vmEvents := 6 // BeingCreated + InstanceUuid + Uuid + Created + Starting + PoweredOn
    47  	tests := []struct {
    48  		obj    types.ManagedObjectReference
    49  		expect int
    50  		ids    []string
    51  	}{
    52  		{root, -1 * count.Machine, nil},
    53  		{root, 1, []string{"SessionEvent"}}, // UserLoginSessionEvent
    54  		{vm.Reference(), 0, []string{"SessionEvent"}},
    55  		{root, count.Machine, []string{"VmCreatedEvent"}},     // concrete type
    56  		{root, count.Machine * vmEvents, []string{"VmEvent"}}, // base type
    57  		{vm.Reference(), 1, []string{"VmCreatedEvent"}},
    58  		{vm.Reference(), vmEvents, nil},
    59  		{host.Reference(), len(host.Vm), []string{"VmCreatedEvent"}},
    60  		{host.Reference(), len(host.Vm) * vmEvents, nil},
    61  	}
    62  
    63  	for i, test := range tests {
    64  		n := 0
    65  		filter := types.EventFilterSpec{
    66  			Entity: &types.EventFilterSpecByEntity{
    67  				Entity:    test.obj,
    68  				Recursion: types.EventFilterSpecRecursionOptionAll,
    69  			},
    70  			EventTypeId: test.ids,
    71  			MaxCount:    100,
    72  		}
    73  
    74  		f := func(obj types.ManagedObjectReference, events []types.BaseEvent) error {
    75  			n += len(events)
    76  
    77  			qevents, qerr := e.QueryEvents(ctx, filter)
    78  			if qerr != nil {
    79  				t.Fatal(qerr)
    80  			}
    81  
    82  			if n != len(qevents) {
    83  				t.Errorf("%d vs %d", n, len(qevents))
    84  			}
    85  
    86  			return nil
    87  		}
    88  
    89  		err = e.Events(ctx, []types.ManagedObjectReference{test.obj}, filter.MaxCount, false, false, f, test.ids...)
    90  		if err != nil {
    91  			t.Fatalf("%d: %s", i, err)
    92  		}
    93  
    94  		if test.expect < 0 {
    95  			expect := test.expect * -1
    96  			if n < expect {
    97  				t.Errorf("%d: expected at least %d events, got: %d", i, expect, n)
    98  			}
    99  			continue
   100  		}
   101  
   102  		if test.expect != n {
   103  			t.Errorf("%d: expected %d events, got: %d", i, test.expect, n)
   104  		}
   105  	}
   106  
   107  	// Test that we don't panic if event ID is not defined in esx.EventInfo
   108  	type TestHostRemovedEvent struct {
   109  		types.HostEvent
   110  	}
   111  	var hre TestHostRemovedEvent
   112  	kind := reflect.TypeOf(hre)
   113  	types.Add(kind.Name(), kind)
   114  
   115  	err = e.PostEvent(ctx, &hre)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  }
   120  
   121  func TestEventManagerRead(t *testing.T) {
   122  	logEvents = testing.Verbose()
   123  	ctx := context.Background()
   124  	m := VPX()
   125  
   126  	defer m.Remove()
   127  
   128  	err := m.Create()
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  
   133  	s := m.Service.NewServer()
   134  	defer s.Close()
   135  
   136  	vc, err := govmomi.NewClient(ctx, s.URL, true)
   137  	if err != nil {
   138  		t.Fatal(err)
   139  	}
   140  
   141  	defer func() {
   142  		if err := vc.Logout(ctx); err != nil {
   143  			t.Fatal(err)
   144  		}
   145  	}()
   146  
   147  	spec := types.EventFilterSpec{
   148  		Entity: &types.EventFilterSpecByEntity{
   149  			Entity:    vc.Client.ServiceContent.RootFolder,
   150  			Recursion: types.EventFilterSpecRecursionOptionChildren,
   151  		},
   152  	}
   153  	em := event.NewManager(vc.Client)
   154  	c, err := em.CreateCollectorForEvents(ctx, spec)
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	page, err := c.LatestPage(ctx)
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	nevents := len(page)
   164  	if nevents == 0 {
   165  		t.Fatal("no recent events")
   166  	}
   167  	tests := []struct {
   168  		max    int
   169  		rewind bool
   170  		order  bool
   171  		read   func(context.Context, int32) ([]types.BaseEvent, error)
   172  	}{
   173  		{nevents, true, true, c.ReadNextEvents},
   174  		{nevents / 3, true, true, c.ReadNextEvents},
   175  		{nevents * 3, false, true, c.ReadNextEvents},
   176  		{3, false, false, c.ReadPreviousEvents},
   177  		{nevents * 3, false, true, c.ReadNextEvents},
   178  	}
   179  
   180  	for _, test := range tests {
   181  		var all []types.BaseEvent
   182  		count := 0
   183  		for {
   184  			events, err := test.read(ctx, int32(test.max))
   185  			if err != nil {
   186  				t.Fatal(err)
   187  			}
   188  			if len(events) == 0 {
   189  				// expecting 0 below as we've read all events in the page
   190  				zevents, nerr := test.read(ctx, int32(test.max))
   191  				if nerr != nil {
   192  					t.Fatal(nerr)
   193  				}
   194  				if len(zevents) != 0 {
   195  					t.Errorf("zevents=%d", len(zevents))
   196  				}
   197  				break
   198  			}
   199  			count += len(events)
   200  			all = append(all, events...)
   201  		}
   202  		if count < len(page) {
   203  			t.Errorf("expected at least %d events, got: %d", len(page), count)
   204  		}
   205  
   206  		for i := 1; i < len(all); i++ {
   207  			prev := all[i-1].GetEvent().Key
   208  			key := all[i].GetEvent().Key
   209  			if test.order {
   210  				if prev > key {
   211  					t.Errorf("key %d > %d", prev, key)
   212  				}
   213  			} else {
   214  				if prev < key {
   215  					t.Errorf("key %d < %d", prev, key)
   216  				}
   217  			}
   218  		}
   219  
   220  		if test.rewind {
   221  			if err = c.Rewind(ctx); err != nil {
   222  				t.Error(err)
   223  			}
   224  		}
   225  	}
   226  
   227  	// after Reset() we should only get events via ReadPreviousEvents
   228  	if err = c.Reset(ctx); err != nil {
   229  		t.Fatal(err)
   230  	}
   231  
   232  	events, err := c.ReadNextEvents(ctx, int32(nevents))
   233  	if err != nil {
   234  		t.Fatal(err)
   235  	}
   236  	if len(events) != 0 {
   237  		t.Errorf("expected 0 events, got %d", len(events))
   238  	}
   239  
   240  	event := &types.GeneralEvent{Message: "vcsim"}
   241  	event.Datacenter = &types.DatacenterEventArgument{
   242  		Datacenter: m.Map().Any("Datacenter").Reference(),
   243  	}
   244  	err = em.PostEvent(ctx, event)
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  
   249  	events, err = c.ReadNextEvents(ctx, int32(nevents))
   250  	if err != nil {
   251  		t.Fatal(err)
   252  	}
   253  	if len(events) != 1 {
   254  		t.Errorf("expected 1 events, got %d", len(events))
   255  	}
   256  
   257  	count := 0
   258  	for {
   259  		events, err = c.ReadPreviousEvents(ctx, 3)
   260  		if err != nil {
   261  			t.Fatal(err)
   262  		}
   263  		if len(events) == 0 {
   264  			break
   265  		}
   266  		count += len(events)
   267  	}
   268  	if count < nevents {
   269  		t.Errorf("expected %d events, got %d", nevents, count)
   270  	}
   271  }