blob: 8cb106284d5e243a2c9919d437a6bb147a5b44bf [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
package objects
import (
"testing"
"gotest.tools/v3/assert"
"github.com/apache/yunikorn-core/pkg/common"
"github.com/apache/yunikorn-core/pkg/events/mock"
"github.com/apache/yunikorn-scheduler-interface/lib/go/si"
)
func isNewApplicationEvent(t *testing.T, app *Application, record *si.EventRecord) {
assert.Equal(t, si.EventRecord_APP, record.Type, "incorrect event type, expect app")
assert.Equal(t, app.ApplicationID, record.ObjectID, "incorrect object ID, expected application ID")
assert.Equal(t, si.EventRecord_ADD, record.EventChangeType, "incorrect change type, expected add")
assert.Equal(t, si.EventRecord_APP_NEW, record.EventChangeDetail, "incorrect change detail, expected none")
}
func isRemoveApplicationEvent(t *testing.T, app *Application, record *si.EventRecord) {
assert.Equal(t, si.EventRecord_APP, record.Type, "incorrect event type, expect app")
assert.Equal(t, app.ApplicationID, record.ObjectID, "incorrect object ID, expected application ID")
assert.Equal(t, si.EventRecord_REMOVE, record.EventChangeType, "incorrect change type, expected remove")
assert.Equal(t, si.EventRecord_DETAILS_NONE, record.EventChangeDetail, "incorrect change detail, expected none")
}
func isStateChangeEvent(t *testing.T, app *Application, changeDetail si.EventRecord_ChangeDetail, record *si.EventRecord) {
assert.Equal(t, si.EventRecord_APP, record.Type, "incorrect event type, expect app")
assert.Equal(t, app.ApplicationID, record.ObjectID, "incorrect object ID, expected application ID")
assert.Equal(t, si.EventRecord_SET, record.EventChangeType, "incorrect change type, expected set")
assert.Equal(t, changeDetail, record.EventChangeDetail, "incorrect change detail")
}
func TestSendPlaceholderLargerEvent(t *testing.T) {
app := &Application{
queuePath: "root.test",
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendPlaceholderLargerEvent(&Allocation{}, &AllocationAsk{})
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendPlaceholderLargerEvent(&Allocation{
allocationKey: aKey,
}, &AllocationAsk{
applicationID: appID0,
allocationKey: aKey,
})
assert.Equal(t, 1, len(eventSystem.Events), "event was not generated")
}
func TestSendNewAllocationEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendNewAllocationEvent(&Allocation{})
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
assert.Assert(t, appEvents.eventSystem != nil, "event system should not be nil")
appEvents.sendNewAllocationEvent(&Allocation{
applicationID: appID0,
allocationKey: aKey,
})
assert.Equal(t, 1, len(eventSystem.Events), "event was not generated")
assert.Equal(t, si.EventRecord_APP, eventSystem.Events[0].Type, "event type is not expected")
assert.Equal(t, si.EventRecord_ADD, eventSystem.Events[0].EventChangeType, "event change type is not expected")
assert.Equal(t, si.EventRecord_APP_ALLOC, eventSystem.Events[0].EventChangeDetail, "event change detail is not expected")
assert.Equal(t, appID0, eventSystem.Events[0].ObjectID, "event object id is not expected")
assert.Equal(t, aKey, eventSystem.Events[0].ReferenceID, "event reference id is not expected")
assert.Equal(t, common.Empty, eventSystem.Events[0].Message, "message is not expected")
}
func TestSendNewAskEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendNewAskEvent(&AllocationAsk{})
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
assert.Assert(t, appEvents.eventSystem != nil, "event system should not be nil")
appEvents.sendNewAskEvent(&AllocationAsk{
applicationID: appID0,
allocationKey: aKey,
})
assert.Equal(t, 1, len(eventSystem.Events), "event was not generated")
assert.Equal(t, si.EventRecord_APP, eventSystem.Events[0].Type, "event type is not expected")
assert.Equal(t, si.EventRecord_ADD, eventSystem.Events[0].EventChangeType, "event change type is not expected")
assert.Equal(t, si.EventRecord_APP_REQUEST, eventSystem.Events[0].EventChangeDetail, "event change detail is not expected")
assert.Equal(t, appID0, eventSystem.Events[0].ObjectID, "event object id is not expected")
assert.Equal(t, aKey, eventSystem.Events[0].ReferenceID, "event reference id is not expected")
assert.Equal(t, common.Empty, eventSystem.Events[0].Message, "message is not expected")
}
func TestSendRemoveAllocationEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendRemoveAllocationEvent(&Allocation{}, si.TerminationType_STOPPED_BY_RM)
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
testCases := []struct {
name string
eventSystemMock *mock.EventSystem
terminationType si.TerminationType
allocation *Allocation
expectedEventCnt int
expectedType si.EventRecord_Type
expectedChangeType si.EventRecord_ChangeType
expectedChangeDetail si.EventRecord_ChangeDetail
expectedObjectID string
expectedReferenceID string
}{
{
name: "remove allocation cause of node removal",
eventSystemMock: mock.NewEventSystem(),
terminationType: si.TerminationType_UNKNOWN_TERMINATION_TYPE,
allocation: &Allocation{applicationID: appID0, allocationKey: aKey},
expectedEventCnt: 1,
expectedType: si.EventRecord_APP,
expectedChangeType: si.EventRecord_REMOVE,
expectedChangeDetail: si.EventRecord_ALLOC_NODEREMOVED,
expectedObjectID: appID0,
expectedReferenceID: aKey,
},
{
name: "remove allocation cause of resource manager cancel",
eventSystemMock: mock.NewEventSystem(),
terminationType: si.TerminationType_STOPPED_BY_RM,
allocation: &Allocation{applicationID: appID0, allocationKey: aKey},
expectedEventCnt: 1,
expectedType: si.EventRecord_APP,
expectedChangeType: si.EventRecord_REMOVE,
expectedChangeDetail: si.EventRecord_ALLOC_CANCEL,
expectedObjectID: appID0,
expectedReferenceID: aKey,
},
{
name: "remove allocation cause of timeout",
eventSystemMock: mock.NewEventSystem(),
terminationType: si.TerminationType_TIMEOUT,
allocation: &Allocation{applicationID: appID0, allocationKey: aKey},
expectedEventCnt: 1,
expectedType: si.EventRecord_APP,
expectedChangeType: si.EventRecord_REMOVE,
expectedChangeDetail: si.EventRecord_ALLOC_TIMEOUT,
expectedObjectID: appID0,
expectedReferenceID: aKey,
},
{
name: "remove allocation cause of preemption",
eventSystemMock: mock.NewEventSystem(),
terminationType: si.TerminationType_PREEMPTED_BY_SCHEDULER,
allocation: &Allocation{applicationID: appID0, allocationKey: aKey},
expectedEventCnt: 1,
expectedType: si.EventRecord_APP,
expectedChangeType: si.EventRecord_REMOVE,
expectedChangeDetail: si.EventRecord_ALLOC_PREEMPT,
expectedObjectID: appID0,
expectedReferenceID: aKey,
},
{
name: "remove allocation cause of replacement",
eventSystemMock: mock.NewEventSystem(),
terminationType: si.TerminationType_PLACEHOLDER_REPLACED,
allocation: &Allocation{applicationID: appID0, allocationKey: aKey},
expectedEventCnt: 1,
expectedType: si.EventRecord_APP,
expectedChangeType: si.EventRecord_REMOVE,
expectedChangeDetail: si.EventRecord_ALLOC_REPLACED,
expectedObjectID: appID0,
expectedReferenceID: aKey,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
if testCase.eventSystemMock == nil {
appEvents := newApplicationEvents(app, nil)
assert.Assert(t, appEvents.eventSystem == nil, "event system should be nil")
appEvents.sendRemoveAllocationEvent(testCase.allocation, testCase.terminationType)
} else {
appEvents := newApplicationEvents(app, testCase.eventSystemMock)
assert.Assert(t, appEvents.eventSystem != nil, "event system should not be nil")
appEvents.sendRemoveAllocationEvent(testCase.allocation, testCase.terminationType)
assert.Equal(t, testCase.expectedEventCnt, len(testCase.eventSystemMock.Events), "event was not generated")
assert.Equal(t, testCase.expectedType, testCase.eventSystemMock.Events[0].Type, "event type is not expected")
assert.Equal(t, testCase.expectedChangeType, testCase.eventSystemMock.Events[0].EventChangeType, "event change type is not expected")
assert.Equal(t, testCase.expectedChangeDetail, testCase.eventSystemMock.Events[0].EventChangeDetail, "event change detail is not expected")
assert.Equal(t, testCase.expectedObjectID, testCase.eventSystemMock.Events[0].ObjectID, "event object id is not expected")
assert.Equal(t, testCase.expectedReferenceID, testCase.eventSystemMock.Events[0].ReferenceID, "event reference id is not expected")
assert.Equal(t, common.Empty, testCase.eventSystemMock.Events[0].Message, "message is not expected")
}
})
}
}
func TestSendRemoveAskEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendRemoveAskEvent(&AllocationAsk{}, si.EventRecord_REQUEST_CANCEL)
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
ask := &AllocationAsk{
applicationID: appID0,
allocationKey: aKey}
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendRemoveAskEvent(ask, si.EventRecord_REQUEST_CANCEL)
event := eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_REMOVE, event.EventChangeType)
assert.Equal(t, si.EventRecord_REQUEST_CANCEL, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "alloc-1", event.ReferenceID)
assert.Equal(t, "", event.Message)
eventSystem.Reset()
appEvents.sendRemoveAskEvent(ask, si.EventRecord_REQUEST_TIMEOUT)
event = eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_REMOVE, event.EventChangeType)
assert.Equal(t, si.EventRecord_REQUEST_TIMEOUT, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "alloc-1", event.ReferenceID)
assert.Equal(t, "", event.Message)
}
func TestSendNewApplicationEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendNewApplicationEvent()
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
mockEvents := mock.NewEventSystem()
appEvents = newApplicationEvents(app, mockEvents)
appEvents.sendNewApplicationEvent()
event := mockEvents.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_ADD, event.EventChangeType)
assert.Equal(t, si.EventRecord_APP_NEW, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "", event.Message)
}
func TestSendRemoveApplicationEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendRemoveApplicationEvent()
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendRemoveApplicationEvent()
event := eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_REMOVE, event.EventChangeType)
assert.Equal(t, si.EventRecord_DETAILS_NONE, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "", event.Message)
}
func TestSendStateChangeEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
sendStateChangeEvents: true,
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendStateChangeEvent(si.EventRecord_APP_RUNNING, "")
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendStateChangeEvent(si.EventRecord_APP_RUNNING, "The application is running")
event := eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_SET, event.EventChangeType)
assert.Equal(t, si.EventRecord_APP_RUNNING, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "The application is running", event.Message)
eventSystem = mock.NewEventSystemDisabled()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendStateChangeEvent(si.EventRecord_APP_RUNNING, "ResourceReservationTimeout")
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendStateChangeEvent(si.EventRecord_APP_REJECT, "Failed to add application to partition (placement rejected)")
event = eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_SET, event.EventChangeType)
assert.Equal(t, si.EventRecord_APP_REJECT, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "Failed to add application to partition (placement rejected)", event.Message)
}
func TestSendAppCannotRunInQueueEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
sendStateChangeEvents: true,
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendAppNotRunnableInQueueEvent()
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendAppNotRunnableInQueueEvent()
event := eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_NONE, event.EventChangeType)
assert.Equal(t, si.EventRecord_APP_CANNOTRUN_QUEUE, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "", event.Message)
}
func TestSendAppCannotRunByQuotaEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
sendStateChangeEvents: true,
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendAppNotRunnableQuotaEvent()
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendAppNotRunnableQuotaEvent()
event := eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_NONE, event.EventChangeType)
assert.Equal(t, si.EventRecord_APP_CANNOTRUN_QUOTA, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "", event.Message)
}
func TestSendAppRunnableInQueueEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
sendStateChangeEvents: true,
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendAppRunnableInQueueEvent()
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendAppRunnableInQueueEvent()
event := eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_NONE, event.EventChangeType)
assert.Equal(t, si.EventRecord_APP_RUNNABLE_QUEUE, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "", event.Message)
}
func TestSendAppRunnableByQuotaEvent(t *testing.T) {
app := &Application{
ApplicationID: appID0,
queuePath: "root.test",
sendStateChangeEvents: true,
}
eventSystem := mock.NewEventSystemDisabled()
appEvents := newApplicationEvents(app, eventSystem)
appEvents.sendAppRunnableQuotaEvent()
assert.Equal(t, 0, len(eventSystem.Events), "unexpected event")
eventSystem = mock.NewEventSystem()
appEvents = newApplicationEvents(app, eventSystem)
appEvents.sendAppRunnableQuotaEvent()
event := eventSystem.Events[0]
assert.Equal(t, si.EventRecord_APP, event.Type)
assert.Equal(t, si.EventRecord_NONE, event.EventChangeType)
assert.Equal(t, si.EventRecord_APP_RUNNABLE_QUOTA, event.EventChangeDetail)
assert.Equal(t, "app-0", event.ObjectID)
assert.Equal(t, "", event.ReferenceID)
assert.Equal(t, "", event.Message)
}