4
0
Эх сурвалжийг харах

increase test coverage on Locate handler

Mike 2 жил өмнө
parent
commit
f6e3948c97

+ 40 - 12
handler/feedbag_manager_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package handler
 
@@ -24,23 +24,27 @@ func (_m *mockFeedbagManager) EXPECT() *mockFeedbagManager_Expecter {
 	return &mockFeedbagManager_Expecter{mock: &_m.Mock}
 }
 
-// Blocked provides a mock function with given fields: sn1, sn2
-func (_m *mockFeedbagManager) Blocked(sn1 string, sn2 string) (state.BlockedState, error) {
-	ret := _m.Called(sn1, sn2)
+// Blocked provides a mock function with given fields: screenName1, screenName2
+func (_m *mockFeedbagManager) Blocked(screenName1 string, screenName2 string) (state.BlockedState, error) {
+	ret := _m.Called(screenName1, screenName2)
+
+	if len(ret) == 0 {
+		panic("no return value specified for Blocked")
+	}
 
 	var r0 state.BlockedState
 	var r1 error
 	if rf, ok := ret.Get(0).(func(string, string) (state.BlockedState, error)); ok {
-		return rf(sn1, sn2)
+		return rf(screenName1, screenName2)
 	}
 	if rf, ok := ret.Get(0).(func(string, string) state.BlockedState); ok {
-		r0 = rf(sn1, sn2)
+		r0 = rf(screenName1, screenName2)
 	} else {
 		r0 = ret.Get(0).(state.BlockedState)
 	}
 
 	if rf, ok := ret.Get(1).(func(string, string) error); ok {
-		r1 = rf(sn1, sn2)
+		r1 = rf(screenName1, screenName2)
 	} else {
 		r1 = ret.Error(1)
 	}
@@ -54,13 +58,13 @@ type mockFeedbagManager_Blocked_Call struct {
 }
 
 // Blocked is a helper method to define mock.On call
-//   - sn1 string
-//   - sn2 string
-func (_e *mockFeedbagManager_Expecter) Blocked(sn1 interface{}, sn2 interface{}) *mockFeedbagManager_Blocked_Call {
-	return &mockFeedbagManager_Blocked_Call{Call: _e.mock.On("Blocked", sn1, sn2)}
+//   - screenName1 string
+//   - screenName2 string
+func (_e *mockFeedbagManager_Expecter) Blocked(screenName1 interface{}, screenName2 interface{}) *mockFeedbagManager_Blocked_Call {
+	return &mockFeedbagManager_Blocked_Call{Call: _e.mock.On("Blocked", screenName1, screenName2)}
 }
 
-func (_c *mockFeedbagManager_Blocked_Call) Run(run func(sn1 string, sn2 string)) *mockFeedbagManager_Blocked_Call {
+func (_c *mockFeedbagManager_Blocked_Call) Run(run func(screenName1 string, screenName2 string)) *mockFeedbagManager_Blocked_Call {
 	_c.Call.Run(func(args mock.Arguments) {
 		run(args[0].(string), args[1].(string))
 	})
@@ -81,6 +85,10 @@ func (_c *mockFeedbagManager_Blocked_Call) RunAndReturn(run func(string, string)
 func (_m *mockFeedbagManager) Buddies(screenName string) ([]string, error) {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for Buddies")
+	}
+
 	var r0 []string
 	var r1 error
 	if rf, ok := ret.Get(0).(func(string) ([]string, error)); ok {
@@ -135,6 +143,10 @@ func (_c *mockFeedbagManager_Buddies_Call) RunAndReturn(run func(string) ([]stri
 func (_m *mockFeedbagManager) Delete(screenName string, items []oscar.FeedbagItem) error {
 	ret := _m.Called(screenName, items)
 
+	if len(ret) == 0 {
+		panic("no return value specified for Delete")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(string, []oscar.FeedbagItem) error); ok {
 		r0 = rf(screenName, items)
@@ -178,6 +190,10 @@ func (_c *mockFeedbagManager_Delete_Call) RunAndReturn(run func(string, []oscar.
 func (_m *mockFeedbagManager) InterestedUsers(screenName string) ([]string, error) {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for InterestedUsers")
+	}
+
 	var r0 []string
 	var r1 error
 	if rf, ok := ret.Get(0).(func(string) ([]string, error)); ok {
@@ -232,6 +248,10 @@ func (_c *mockFeedbagManager_InterestedUsers_Call) RunAndReturn(run func(string)
 func (_m *mockFeedbagManager) LastModified(screenName string) (time.Time, error) {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for LastModified")
+	}
+
 	var r0 time.Time
 	var r1 error
 	if rf, ok := ret.Get(0).(func(string) (time.Time, error)); ok {
@@ -284,6 +304,10 @@ func (_c *mockFeedbagManager_LastModified_Call) RunAndReturn(run func(string) (t
 func (_m *mockFeedbagManager) Retrieve(screenName string) ([]oscar.FeedbagItem, error) {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for Retrieve")
+	}
+
 	var r0 []oscar.FeedbagItem
 	var r1 error
 	if rf, ok := ret.Get(0).(func(string) ([]oscar.FeedbagItem, error)); ok {
@@ -338,6 +362,10 @@ func (_c *mockFeedbagManager_Retrieve_Call) RunAndReturn(run func(string) ([]osc
 func (_m *mockFeedbagManager) Upsert(screenName string, items []oscar.FeedbagItem) error {
 	ret := _m.Called(screenName, items)
 
+	if len(ret) == 0 {
+		panic("no return value specified for Upsert")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(string, []oscar.FeedbagItem) error); ok {
 		r0 = rf(screenName, items)

+ 24 - 6
handler/locate.go

@@ -7,6 +7,7 @@ import (
 	"github.com/mkaminski/goaim/state"
 )
 
+// NewLocateService creates a new instance of LocateService.
 func NewLocateService(messageRelayer MessageRelayer, feedbagManager FeedbagManager, profileManager ProfileManager) LocateService {
 	return LocateService{
 		sessionManager: messageRelayer,
@@ -15,12 +16,15 @@ func NewLocateService(messageRelayer MessageRelayer, feedbagManager FeedbagManag
 	}
 }
 
+// LocateService provides handlers for the Locate food group.
 type LocateService struct {
 	sessionManager MessageRelayer
 	feedbagManager FeedbagManager
 	profileManager ProfileManager
 }
 
+// RightsQueryHandler returns SNAC oscar.LocateRightsReply, which contains
+// Locate food group settings for the current user.
 func (s LocateService) RightsQueryHandler(_ context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	return oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
@@ -31,17 +35,20 @@ func (s LocateService) RightsQueryHandler(_ context.Context, inFrame oscar.SNACF
 		Body: oscar.SNAC_0x02_0x03_LocateRightsReply{
 			TLVRestBlock: oscar.TLVRestBlock{
 				TLVList: oscar.TLVList{
-					oscar.NewTLV(0x01, uint16(1000)),
-					oscar.NewTLV(0x02, uint16(1000)),
-					oscar.NewTLV(0x03, uint16(1000)),
-					oscar.NewTLV(0x04, uint16(1000)),
-					oscar.NewTLV(0x05, uint16(1000)),
+					// these are arbitrary values--AIM clients seem to perform
+					// OK with them
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxSigLen, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxCapabilitiesLen, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxFindByEmailList, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxCertsLen, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxMaxShortCapabilities, uint16(1000)),
 				},
 			},
 		},
 	}
 }
 
+// SetInfoHandler sets the user's profile or away message.
 func (s LocateService) SetInfoHandler(ctx context.Context, sess *state.Session, inBody oscar.SNAC_0x02_0x04_LocateSetInfo) error {
 	// update profile
 	if profile, hasProfile := inBody.GetString(oscar.LocateTLVTagsInfoSigData); hasProfile {
@@ -60,6 +67,10 @@ func (s LocateService) SetInfoHandler(ctx context.Context, sess *state.Session,
 	return nil
 }
 
+// UserInfoQuery2Handler fetches display information about an arbitrary user
+// (not the current user). It returns oscar.LocateUserInfoReply, which contains
+// the profile, if requested, and/or the away message, if requested. This is a
+// v2 of the UserInfoQueryHandler handler.
 func (s LocateService) UserInfoQuery2Handler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x02_0x15_LocateUserInfoQuery2) (oscar.SNACMessage, error) {
 	blocked, err := s.feedbagManager.Blocked(sess.ScreenName(), inBody.ScreenName)
 	switch {
@@ -127,11 +138,15 @@ func (s LocateService) UserInfoQuery2Handler(ctx context.Context, sess *state.Se
 	}, nil
 }
 
-func (s LocateService) SetDirInfoHandler(_ context.Context) oscar.SNACMessage {
+// SetDirInfoHandler sets directory information for current user (first name,
+// last name, etc). This method does nothing and exists to placate the AIM
+// client. It returns oscar.LocateSetDirReply with a canned success message.
+func (s LocateService) SetDirInfoHandler(_ context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	return oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Locate,
 			SubGroup:  oscar.LocateSetDirReply,
+			RequestID: inFrame.RequestID,
 		},
 		Body: oscar.SNAC_0x02_0x0A_LocateSetDirReply{
 			Result: 1,
@@ -139,6 +154,9 @@ func (s LocateService) SetDirInfoHandler(_ context.Context) oscar.SNACMessage {
 	}
 }
 
+// SetKeywordInfoHandler sets profile keywords and interests. This method does
+// nothing and exists to placate the AIM client. It returns
+// oscar.LocateSetKeywordReply with a canned success message.
 func (s LocateService) SetKeywordInfoHandler(_ context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	return oscar.SNACMessage{
 		Frame: oscar.SNACFrame{

+ 298 - 100
handler/locate_test.go

@@ -4,46 +4,48 @@ import (
 	"context"
 	"testing"
 
+	"github.com/stretchr/testify/mock"
+
 	"github.com/mkaminski/goaim/oscar"
 	"github.com/mkaminski/goaim/state"
 	"github.com/stretchr/testify/assert"
 )
 
-func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
+func TestLocateService_UserInfoQuery2Handler(t *testing.T) {
 	cases := []struct {
 		// name is the unit test name
 		name string
-		// blockedState is the response to the sender/recipient block check
-		blockedState state.BlockedState
-		// screenNameLookups is the list of user session lookups
-		screenNameLookups map[string]struct {
-			sess *state.Session
-			err  error
-		}
-		// screenNameLookups is the list of user session lookups
-		profileLookups map[string]struct {
-			payload string
-			err     error
-		}
-		// userSession is the session of the user requesting the user info
+		// mockParams is the list of params sent to mocks that satisfy this
+		// method's dependencies
+		mockParams mockParams
+		// userSession is the session of the user requesting user info
 		userSession *state.Session
-		// inputSNAC is the SNAC sent by the sender client
+		// inputSNAC is the SNAC sent from client to server
 		inputSNAC oscar.SNACMessage
-		// expectOutput is the SNAC sent from the server to the
-		// recipient client
+		// expectOutput is the SNAC sent from the server to client
 		expectOutput oscar.SNACMessage
 	}{
 		{
-			name:         "request user info, expect user info response",
-			blockedState: state.BlockedNo,
-			screenNameLookups: map[string]struct {
-				sess *state.Session
-				err  error
-			}{
-				"requested-user": {
-					sess: newTestSession("requested-user",
-						sessOptCannedSignonTime,
-						sessOptCannedAwayMessage),
+			name: "request user info, expect user info response",
+			mockParams: mockParams{
+				feedbagManagerParams: feedbagManagerParams{
+					blockedParams: blockedParams{
+						{
+							screenName1: "user_screen_name",
+							screenName2: "requested-user",
+							result:      state.BlockedNo,
+						},
+					},
+				},
+				messageRelayerParams: messageRelayerParams{
+					retrieveByScreenNameParams: retrieveByScreenNameParams{
+						{
+							screenName: "requested-user",
+							sess: newTestSession("requested-user",
+								sessOptCannedSignonTime,
+								sessOptCannedAwayMessage),
+						},
+					},
 				},
 			},
 			userSession: newTestSession("user_screen_name"),
@@ -72,24 +74,34 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 			},
 		},
 		{
-			name:         "request user info + profile, expect user info response + profile",
-			blockedState: state.BlockedNo,
-			screenNameLookups: map[string]struct {
-				sess *state.Session
-				err  error
-			}{
-				"requested-user": {
-					sess: newTestSession("requested-user",
-						sessOptCannedSignonTime,
-						sessOptCannedAwayMessage),
+			name: "request user info + profile, expect user info response + profile",
+			mockParams: mockParams{
+				feedbagManagerParams: feedbagManagerParams{
+					blockedParams: blockedParams{
+						{
+							screenName1: "user_screen_name",
+							screenName2: "requested-user",
+							result:      state.BlockedNo,
+						},
+					},
 				},
-			},
-			profileLookups: map[string]struct {
-				payload string
-				err     error
-			}{
-				"requested-user": {
-					payload: "this is my profile!",
+				messageRelayerParams: messageRelayerParams{
+					retrieveByScreenNameParams: retrieveByScreenNameParams{
+						{
+							screenName: "requested-user",
+							sess: newTestSession("requested-user",
+								sessOptCannedSignonTime,
+								sessOptCannedAwayMessage),
+						},
+					},
+				},
+				profileManagerParams: profileManagerParams{
+					retrieveProfileParams: retrieveProfileParams{
+						{
+							screenName: "requested-user",
+							result:     "this is my profile!",
+						},
+					},
 				},
 			},
 			userSession: newTestSession("user_screen_name"),
@@ -124,24 +136,34 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 			},
 		},
 		{
-			name:         "request user info + profile, expect user info response + profile",
-			blockedState: state.BlockedNo,
-			screenNameLookups: map[string]struct {
-				sess *state.Session
-				err  error
-			}{
-				"requested-user": {
-					sess: newTestSession("requested-user",
-						sessOptCannedSignonTime,
-						sessOptCannedAwayMessage),
+			name: "request user info + profile, expect user info response + profile",
+			mockParams: mockParams{
+				feedbagManagerParams: feedbagManagerParams{
+					blockedParams: blockedParams{
+						{
+							screenName1: "user_screen_name",
+							screenName2: "requested-user",
+							result:      state.BlockedNo,
+						},
+					},
 				},
-			},
-			profileLookups: map[string]struct {
-				payload string
-				err     error
-			}{
-				"requested-user": {
-					payload: "this is my profile!",
+				messageRelayerParams: messageRelayerParams{
+					retrieveByScreenNameParams: retrieveByScreenNameParams{
+						{
+							screenName: "requested-user",
+							sess: newTestSession("requested-user",
+								sessOptCannedSignonTime,
+								sessOptCannedAwayMessage),
+						},
+					},
+				},
+				profileManagerParams: profileManagerParams{
+					retrieveProfileParams: retrieveProfileParams{
+						{
+							screenName: "requested-user",
+							result:     "this is my profile!",
+						},
+					},
 				},
 			},
 			userSession: newTestSession("user_screen_name"),
@@ -176,16 +198,26 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 			},
 		},
 		{
-			name:         "request user info + away message, expect user info response + away message",
-			blockedState: state.BlockedNo,
-			screenNameLookups: map[string]struct {
-				sess *state.Session
-				err  error
-			}{
-				"requested-user": {
-					sess: newTestSession("requested-user",
-						sessOptCannedSignonTime,
-						sessOptCannedAwayMessage),
+			name: "request user info + away message, expect user info response + away message",
+			mockParams: mockParams{
+				feedbagManagerParams: feedbagManagerParams{
+					blockedParams: blockedParams{
+						{
+							screenName1: "user_screen_name",
+							screenName2: "requested-user",
+							result:      state.BlockedNo,
+						},
+					},
+				},
+				messageRelayerParams: messageRelayerParams{
+					retrieveByScreenNameParams: retrieveByScreenNameParams{
+						{
+							screenName: "requested-user",
+							sess: newTestSession("requested-user",
+								sessOptCannedSignonTime,
+								sessOptCannedAwayMessage),
+						},
+					},
 				},
 			},
 			userSession: newTestSession("user_screen_name"),
@@ -220,9 +252,19 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 			},
 		},
 		{
-			name:         "request user info of user who blocked requester, expect not logged in error",
-			blockedState: state.BlockedB,
-			userSession:  newTestSession("user_screen_name"),
+			name: "request user info of user who blocked requester, expect not logged in error",
+			mockParams: mockParams{
+				feedbagManagerParams: feedbagManagerParams{
+					blockedParams: blockedParams{
+						{
+							screenName1: "user_screen_name",
+							screenName2: "requested-user",
+							result:      state.BlockedB,
+						},
+					},
+				},
+			},
+			userSession: newTestSession("user_screen_name"),
 			inputSNAC: oscar.SNACMessage{
 				Frame: oscar.SNACFrame{
 					RequestID: 1234,
@@ -243,14 +285,24 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 			},
 		},
 		{
-			name:         "request user info of user who does not exist, expect not logged in error",
-			blockedState: state.BlockedNo,
-			screenNameLookups: map[string]struct {
-				sess *state.Session
-				err  error
-			}{
-				"non_existent_requested_user": {
-					sess: nil,
+			name: "request user info of user who does not exist, expect not logged in error",
+			mockParams: mockParams{
+				feedbagManagerParams: feedbagManagerParams{
+					blockedParams: blockedParams{
+						{
+							screenName1: "user_screen_name",
+							screenName2: "non_existent_requested_user",
+							result:      state.BlockedNo,
+						},
+					},
+				},
+				messageRelayerParams: messageRelayerParams{
+					retrieveByScreenNameParams: retrieveByScreenNameParams{
+						{
+							screenName: "non_existent_requested_user",
+							sess:       nil,
+						},
+					},
 				},
 			},
 			userSession: newTestSession("user_screen_name"),
@@ -278,30 +330,24 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 	for _, tc := range cases {
 		t.Run(tc.name, func(t *testing.T) {
 			feedbagManager := newMockFeedbagManager(t)
-			feedbagManager.EXPECT().
-				Blocked(tc.userSession.ScreenName(),
-					tc.inputSNAC.Body.(oscar.SNAC_0x02_0x15_LocateUserInfoQuery2).ScreenName).
-				Return(tc.blockedState, nil).
-				Maybe()
+			for _, params := range tc.mockParams.blockedParams {
+				feedbagManager.EXPECT().
+					Blocked(params.screenName1, params.screenName2).
+					Return(params.result, nil)
+			}
 			messageRelayer := newMockMessageRelayer(t)
-			for screenName, val := range tc.screenNameLookups {
+			for _, val := range tc.mockParams.retrieveByScreenNameParams {
 				messageRelayer.EXPECT().
-					RetrieveByScreenName(screenName).
-					Return(val.sess).
-					Maybe()
+					RetrieveByScreenName(val.screenName).
+					Return(val.sess)
 			}
 			profileManager := newMockProfileManager(t)
-			for screenName, val := range tc.profileLookups {
+			for _, val := range tc.mockParams.retrieveProfileParams {
 				profileManager.EXPECT().
-					RetrieveProfile(screenName).
-					Return(val.payload, val.err).
-					Maybe()
-			}
-			svc := LocateService{
-				sessionManager: messageRelayer,
-				feedbagManager: feedbagManager,
-				profileManager: profileManager,
+					RetrieveProfile(val.screenName).
+					Return(val.result, val.err)
 			}
+			svc := NewLocateService(messageRelayer, feedbagManager, profileManager)
 			outputSNAC, err := svc.UserInfoQuery2Handler(context.Background(), tc.userSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x02_0x15_LocateUserInfoQuery2))
 			assert.NoError(t, err)
@@ -309,3 +355,155 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 		})
 	}
 }
+
+func TestLocateService_SetKeywordInfoHandler(t *testing.T) {
+	svc := NewLocateService(nil, nil, nil)
+
+	outputSNAC := svc.SetKeywordInfoHandler(nil, oscar.SNACFrame{RequestID: 1234})
+	expectSNAC := oscar.SNACMessage{
+		Frame: oscar.SNACFrame{
+			FoodGroup: oscar.Locate,
+			SubGroup:  oscar.LocateSetKeywordReply,
+			RequestID: 1234,
+		},
+		Body: oscar.SNAC_0x02_0x10_LocateSetKeywordReply{
+			Unknown: 1,
+		},
+	}
+
+	assert.Equal(t, expectSNAC, outputSNAC)
+}
+
+func TestLocateService_SetDirInfoHandler(t *testing.T) {
+	svc := NewLocateService(nil, nil, nil)
+
+	outputSNAC := svc.SetDirInfoHandler(nil, oscar.SNACFrame{RequestID: 1234})
+	expectSNAC := oscar.SNACMessage{
+		Frame: oscar.SNACFrame{
+			FoodGroup: oscar.Locate,
+			SubGroup:  oscar.LocateSetDirReply,
+			RequestID: 1234,
+		},
+		Body: oscar.SNAC_0x02_0x0A_LocateSetDirReply{
+			Result: 1,
+		},
+	}
+
+	assert.Equal(t, expectSNAC, outputSNAC)
+}
+
+func TestLocateService_SetInfoHandler(t *testing.T) {
+	tests := []struct {
+		// name is the unit test name
+		name string
+		// userSession is the session of the user setting info
+		userSession *state.Session
+		// inBody is the message sent from client to server
+		inBody oscar.SNAC_0x02_0x04_LocateSetInfo
+		// mockParams is the list of params sent to mocks that satisfy this
+		// method's dependencies
+		mockParams mockParams
+		wantErr    error
+	}{
+		{
+			name:        "set profile",
+			userSession: newTestSession("test-user"),
+			inBody: oscar.SNAC_0x02_0x04_LocateSetInfo{
+				TLVRestBlock: oscar.TLVRestBlock{
+					TLVList: oscar.TLVList{
+						oscar.NewTLV(oscar.LocateTLVTagsInfoSigData, "profile-result"),
+					},
+				},
+			},
+		},
+		{
+			name:        "set away message",
+			userSession: newTestSession("user_screen_name"),
+			inBody: oscar.SNAC_0x02_0x04_LocateSetInfo{
+				TLVRestBlock: oscar.TLVRestBlock{
+					TLVList: oscar.TLVList{
+						oscar.NewTLV(oscar.LocateTLVTagsInfoUnavailableData, "this is my away message!"),
+					},
+				},
+			},
+			mockParams: mockParams{
+				messageRelayerParams: messageRelayerParams{
+					broadcastToScreenNamesParams: broadcastToScreenNamesParams{
+						{
+							screenNames: []string{"friend1", "friend2"},
+							message: oscar.SNACMessage{
+								Frame: oscar.SNACFrame{
+									FoodGroup: oscar.Buddy,
+									SubGroup:  oscar.BuddyArrived,
+								},
+								Body: oscar.SNAC_0x03_0x0B_BuddyArrived{
+									TLVUserInfo: newTestSession("user_screen_name", sessOptAwayMessage("this is my away message!")).TLVUserInfo(),
+								},
+							},
+						},
+					},
+				},
+				feedbagManagerParams: feedbagManagerParams{
+					interestedUsersParams: interestedUsersParams{
+						{
+							screenName: "user_screen_name",
+							users:      []string{"friend1", "friend2"},
+						},
+					},
+				},
+				profileManagerParams: profileManagerParams{
+					upsertProfileParams: upsertProfileParams{},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			messageRelayer := newMockMessageRelayer(t)
+			for _, params := range tt.mockParams.broadcastToScreenNamesParams {
+				messageRelayer.EXPECT().
+					BroadcastToScreenNames(mock.Anything, params.screenNames, params.message)
+			}
+			feedbagManager := newMockFeedbagManager(t)
+			for _, params := range tt.mockParams.interestedUsersParams {
+				feedbagManager.EXPECT().
+					InterestedUsers(params.screenName).
+					Return(params.users, nil)
+			}
+			profileManager := newMockProfileManager(t)
+			if msg, hasProf := tt.inBody.GetString(oscar.LocateTLVTagsInfoSigData); hasProf {
+				profileManager.EXPECT().
+					UpsertProfile(tt.userSession.ScreenName(), msg).
+					Return(nil)
+			}
+			svc := NewLocateService(messageRelayer, feedbagManager, profileManager)
+			assert.Equal(t, tt.wantErr, svc.SetInfoHandler(nil, tt.userSession, tt.inBody))
+		})
+	}
+}
+
+func TestLocateService_RightsQueryHandler(t *testing.T) {
+	svc := NewLocateService(nil, nil, nil)
+
+	outputSNAC := svc.RightsQueryHandler(nil, oscar.SNACFrame{RequestID: 1234})
+	expectSNAC := oscar.SNACMessage{
+		Frame: oscar.SNACFrame{
+			FoodGroup: oscar.Locate,
+			SubGroup:  oscar.LocateRightsReply,
+			RequestID: 1234,
+		},
+		Body: oscar.SNAC_0x02_0x03_LocateRightsReply{
+			TLVRestBlock: oscar.TLVRestBlock{
+				TLVList: oscar.TLVList{
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxSigLen, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxCapabilitiesLen, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxFindByEmailList, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxCertsLen, uint16(1000)),
+					oscar.NewTLV(oscar.LocateTLVTagsRightsMaxMaxShortCapabilities, uint16(1000)),
+				},
+			},
+		},
+	}
+
+	assert.Equal(t, expectSNAC, outputSNAC)
+}

+ 1 - 1
handler/oservice.go

@@ -17,7 +17,7 @@ func NewOServiceService(cfg server.Config, messageRelayer MessageRelayer, feedba
 	return &OServiceService{cfg: cfg, messageRelayer: messageRelayer, feedbagManager: feedbagManager}
 }
 
-// OServiceService contains handlers for the OService food group.
+// OServiceService provides handlers for the OService food group.
 type OServiceService struct {
 	cfg            server.Config
 	feedbagManager FeedbagManager

+ 0 - 12
handler/oservice_test.go

@@ -672,18 +672,6 @@ func TestOServiceServiceForBOS_ClientOnlineHandler(t *testing.T) {
 		screenName string
 		buddies    []string
 	}
-	type interestedUsersParams []struct {
-		screenName string
-		users      []string
-	}
-	type broadcastToScreenNamesParams []struct {
-		screenNames []string
-		message     oscar.SNACMessage
-	}
-	type retrieveByScreenNameParams []struct {
-		screenName string
-		sess       *state.Session
-	}
 	type sendToScreenNameParams []struct {
 		screenName string
 		message    oscar.SNACMessage

+ 9 - 1
handler/profile_manager_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package handler
 
@@ -21,6 +21,10 @@ func (_m *mockProfileManager) EXPECT() *mockProfileManager_Expecter {
 func (_m *mockProfileManager) RetrieveProfile(screenName string) (string, error) {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RetrieveProfile")
+	}
+
 	var r0 string
 	var r1 error
 	if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
@@ -73,6 +77,10 @@ func (_c *mockProfileManager_RetrieveProfile_Call) RunAndReturn(run func(string)
 func (_m *mockProfileManager) UpsertProfile(screenName string, body string) error {
 	ret := _m.Called(screenName, body)
 
+	if len(ret) == 0 {
+		panic("no return value specified for UpsertProfile")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(string, string) error); ok {
 		r0 = rf(screenName, body)

+ 9 - 1
handler/session_chat_message_relayer.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package handler
 
@@ -98,6 +98,10 @@ func (_c *mockChatMessageRelayer_BroadcastToScreenNames_Call) RunAndReturn(run f
 func (_m *mockChatMessageRelayer) Participants() []*state.Session {
 	ret := _m.Called()
 
+	if len(ret) == 0 {
+		panic("no return value specified for Participants")
+	}
+
 	var r0 []*state.Session
 	if rf, ok := ret.Get(0).(func() []*state.Session); ok {
 		r0 = rf()
@@ -141,6 +145,10 @@ func (_c *mockChatMessageRelayer_Participants_Call) RunAndReturn(run func() []*s
 func (_m *mockChatMessageRelayer) RetrieveByScreenName(screenName string) *state.Session {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RetrieveByScreenName")
+	}
+
 	var r0 *state.Session
 	if rf, ok := ret.Get(0).(func(string) *state.Session); ok {
 		r0 = rf(screenName)

+ 13 - 1
handler/session_manager_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package handler
 
@@ -24,6 +24,10 @@ func (_m *mockSessionManager) EXPECT() *mockSessionManager_Expecter {
 func (_m *mockSessionManager) Empty() bool {
 	ret := _m.Called()
 
+	if len(ret) == 0 {
+		panic("no return value specified for Empty")
+	}
+
 	var r0 bool
 	if rf, ok := ret.Get(0).(func() bool); ok {
 		r0 = rf()
@@ -65,6 +69,10 @@ func (_c *mockSessionManager_Empty_Call) RunAndReturn(run func() bool) *mockSess
 func (_m *mockSessionManager) NewSessionWithSN(sessID string, screenName string) *state.Session {
 	ret := _m.Called(sessID, screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for NewSessionWithSN")
+	}
+
 	var r0 *state.Session
 	if rf, ok := ret.Get(0).(func(string, string) *state.Session); ok {
 		r0 = rf(sessID, screenName)
@@ -143,6 +151,10 @@ func (_c *mockSessionManager_Remove_Call) RunAndReturn(run func(*state.Session))
 func (_m *mockSessionManager) Retrieve(ID string) (*state.Session, bool) {
 	ret := _m.Called(ID)
 
+	if len(ret) == 0 {
+		panic("no return value specified for Retrieve")
+	}
+
 	var r0 *state.Session
 	var r1 bool
 	if rf, ok := ret.Get(0).(func(string) (*state.Session, bool)); ok {

+ 5 - 1
handler/session_message_relayer.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package handler
 
@@ -63,6 +63,10 @@ func (_c *mockMessageRelayer_BroadcastToScreenNames_Call) RunAndReturn(run func(
 func (_m *mockMessageRelayer) RetrieveByScreenName(screenName string) *state.Session {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RetrieveByScreenName")
+	}
+
 	var r0 *state.Session
 	if rf, ok := ret.Get(0).(func(string) *state.Session); ok {
 		r0 = rf(screenName)

+ 82 - 0
handler/test_helpers.go

@@ -3,9 +3,84 @@ package handler
 import (
 	"time"
 
+	"github.com/mkaminski/goaim/oscar"
 	"github.com/mkaminski/goaim/state"
 )
 
+// mockParams is a helper struct that centralizes mock function call parameters
+// in one place for a table test
+type mockParams struct {
+	feedbagManagerParams
+	messageRelayerParams
+	profileManagerParams
+}
+
+// feedbagManagerParams is a helper struct that contains mock parameters for
+// FeedbagManager methods
+type feedbagManagerParams struct {
+	blockedParams
+	interestedUsersParams
+}
+
+// blockedParams is the list of parameters passed at the mock
+// FeedbagManager.Blocked call site
+type blockedParams []struct {
+	screenName1 string
+	screenName2 string
+	result      state.BlockedState
+	err         error
+}
+
+// interestedUsersParams is the list of parameters passed at the mock
+// FeedbagManager.InterestedUsers call site
+type interestedUsersParams []struct {
+	screenName string
+	users      []string
+}
+
+// messageRelayerParams is a helper struct that contains mock parameters for
+// MessageRelayer methods
+type messageRelayerParams struct {
+	retrieveByScreenNameParams
+	broadcastToScreenNamesParams
+}
+
+// retrieveByScreenNameParams is the list of parameters passed at the mock
+// MessageRelayer.RetrieveByScreenName call site
+type retrieveByScreenNameParams []struct {
+	screenName string
+	sess       *state.Session
+}
+
+// broadcastToScreenNamesParams is the list of parameters passed at the mock
+// MessageRelayer.BroadcastToScreenNames call site
+type broadcastToScreenNamesParams []struct {
+	screenNames []string
+	message     oscar.SNACMessage
+}
+
+// profileManagerParams is a helper struct that contains mock parameters for
+// ProfileManager methods
+type profileManagerParams struct {
+	retrieveProfileParams
+	upsertProfileParams
+}
+
+// retrieveByScreenNameParams is the list of parameters passed at the mock
+// ProfileManager.RetrieveProfile call site
+type retrieveProfileParams []struct {
+	screenName string
+	result     string
+	err        error
+}
+
+// upsertProfileParams is the list of parameters passed at the mock
+// ProfileManager.UpsertProfile call site
+type upsertProfileParams []struct {
+	screenName string
+	body       any
+}
+
 // sessOptWarning sets a warning level on the session object
 func sessOptWarning(level uint16) func(session *state.Session) {
 	return func(session *state.Session) {
@@ -27,6 +102,13 @@ func sessOptID(ID string) func(session *state.Session) {
 	}
 }
 
+// sessOptAwayMessage sets away message on the session object
+func sessOptAwayMessage(awayMessage string) func(session *state.Session) {
+	return func(session *state.Session) {
+		session.SetAwayMessage(awayMessage)
+	}
+}
+
 // sessOptCannedAwayMessage sets a canned away message ("this is my away
 // message!") on the session object
 func sessOptCannedAwayMessage(session *state.Session) {

+ 1 - 1
handler/types.go

@@ -9,7 +9,7 @@ import (
 )
 
 type FeedbagManager interface {
-	Blocked(sn1, sn2 string) (state.BlockedState, error)
+	Blocked(screenName1, screenName2 string) (state.BlockedState, error)
 	Buddies(screenName string) ([]string, error)
 	Delete(screenName string, items []oscar.FeedbagItem) error
 	InterestedUsers(screenName string) ([]string, error)

+ 9 - 1
handler/user_manager_manager_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package handler
 
@@ -24,6 +24,10 @@ func (_m *mockUserManager) EXPECT() *mockUserManager_Expecter {
 func (_m *mockUserManager) GetUser(screenName string) (*state.User, error) {
 	ret := _m.Called(screenName)
 
+	if len(ret) == 0 {
+		panic("no return value specified for GetUser")
+	}
+
 	var r0 *state.User
 	var r1 error
 	if rf, ok := ret.Get(0).(func(string) (*state.User, error)); ok {
@@ -78,6 +82,10 @@ func (_c *mockUserManager_GetUser_Call) RunAndReturn(run func(string) (*state.Us
 func (_m *mockUserManager) UpsertUser(u state.User) error {
 	ret := _m.Called(u)
 
+	if len(ret) == 0 {
+		panic("no return value specified for UpsertUser")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(state.User) error); ok {
 		r0 = rf(u)

+ 12 - 0
oscar/snacs.go

@@ -270,6 +270,17 @@ const (
 	LocateTLVTagsInfoSupportHostSig  uint16 = 0x0C
 	LocateTLVTagsInfoHtmlInfoData    uint16 = 0x0E
 	LocateTLVTagsInfoHtmlInfoType    uint16 = 0x0D
+
+	// LocateTLVTagsRightsMaxSigLen is the max signature length
+	LocateTLVTagsRightsMaxSigLen uint16 = 0x01
+	// LocateTLVTagsRightsMaxCapabilitiesLen is the max allowed # of full UUID capabilities
+	LocateTLVTagsRightsMaxCapabilitiesLen uint16 = 0x02
+	// LocateTLVTagsRightsMaxFindByEmailList is the maximum # of email addresses to look up at once
+	LocateTLVTagsRightsMaxFindByEmailList uint16 = 0x03
+	// LocateTLVTagsRightsMaxCertsLen is the largest CERT length for e2e crypto
+	LocateTLVTagsRightsMaxCertsLen uint16 = 0x04
+	// LocateTLVTagsRightsMaxMaxShortCapabilities is the max allowed # of short UUID capabilities allowed
+	LocateTLVTagsRightsMaxMaxShortCapabilities uint16 = 0x05
 )
 
 type SNAC_0x02_0x03_LocateRightsReply struct {
@@ -302,6 +313,7 @@ type SNAC_0x02_0x0F_LocateSetKeywordInfo struct {
 }
 
 type SNAC_0x02_0x10_LocateSetKeywordReply struct {
+	// Unknown is a field whose purpose is not known
 	Unknown uint16
 }
 

+ 5 - 1
server/buddy_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -26,6 +26,10 @@ func (_m *mockBuddyHandler) EXPECT() *mockBuddyHandler_Expecter {
 func (_m *mockBuddyHandler) RightsQueryHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, inFrame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RightsQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, inFrame)

+ 5 - 1
server/chat_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockChatHandler) EXPECT() *mockChatHandler_Expecter {
 func (_m *mockChatHandler) ChannelMsgToHostHandler(ctx context.Context, sess *state.Session, chatID string, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost) (*oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, chatID, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ChannelMsgToHostHandler")
+	}
+
 	var r0 *oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, string, oscar.SNACFrame, oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost) (*oscar.SNACMessage, error)); ok {

+ 13 - 1
server/chat_nav_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockChatNavHandler) EXPECT() *mockChatNavHandler_Expecter {
 func (_m *mockChatNavHandler) CreateRoomHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for CreateRoomHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x0E_0x02_ChatRoomInfoUpdate) (oscar.SNACMessage, error)); ok {
@@ -83,6 +87,10 @@ func (_c *mockChatNavHandler_CreateRoomHandler_Call) RunAndReturn(run func(conte
 func (_m *mockChatNavHandler) RequestChatRightsHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, inFrame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RequestChatRightsHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, inFrame)
@@ -126,6 +134,10 @@ func (_c *mockChatNavHandler_RequestChatRightsHandler_Call) RunAndReturn(run fun
 func (_m *mockChatNavHandler) RequestRoomInfoHandler(ctx context.Context, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x0D_0x04_ChatNavRequestRoomInfo) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RequestRoomInfoHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame, oscar.SNAC_0x0D_0x04_ChatNavRequestRoomInfo) (oscar.SNACMessage, error)); ok {

+ 25 - 1
server/feedbag_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockFeedbagHandler) EXPECT() *mockFeedbagHandler_Expecter {
 func (_m *mockFeedbagHandler) DeleteItemHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x13_0x0A_FeedbagDeleteItem) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for DeleteItemHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x13_0x0A_FeedbagDeleteItem) (oscar.SNACMessage, error)); ok {
@@ -83,6 +87,10 @@ func (_c *mockFeedbagHandler_DeleteItemHandler_Call) RunAndReturn(run func(conte
 func (_m *mockFeedbagHandler) InsertItemHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x13_0x08_FeedbagInsertItem) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for InsertItemHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x13_0x08_FeedbagInsertItem) (oscar.SNACMessage, error)); ok {
@@ -138,6 +146,10 @@ func (_c *mockFeedbagHandler_InsertItemHandler_Call) RunAndReturn(run func(conte
 func (_m *mockFeedbagHandler) QueryHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for QueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame) (oscar.SNACMessage, error)); ok {
@@ -192,6 +204,10 @@ func (_c *mockFeedbagHandler_QueryHandler_Call) RunAndReturn(run func(context.Co
 func (_m *mockFeedbagHandler) QueryIfModifiedHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x13_0x05_FeedbagQueryIfModified) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for QueryIfModifiedHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x13_0x05_FeedbagQueryIfModified) (oscar.SNACMessage, error)); ok {
@@ -247,6 +263,10 @@ func (_c *mockFeedbagHandler_QueryIfModifiedHandler_Call) RunAndReturn(run func(
 func (_m *mockFeedbagHandler) RightsQueryHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, inFrame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RightsQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, inFrame)
@@ -325,6 +345,10 @@ func (_c *mockFeedbagHandler_StartClusterHandler_Call) RunAndReturn(run func(con
 func (_m *mockFeedbagHandler) UpdateItemHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x13_0x09_FeedbagUpdateItem) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for UpdateItemHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x13_0x09_FeedbagUpdateItem) (oscar.SNACMessage, error)); ok {

+ 17 - 1
server/icbm_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockICBMHandler) EXPECT() *mockICBMHandler_Expecter {
 func (_m *mockICBMHandler) ChannelMsgToHostHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x04_0x06_ICBMChannelMsgToHost) (*oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ChannelMsgToHostHandler")
+	}
+
 	var r0 *oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x04_0x06_ICBMChannelMsgToHost) (*oscar.SNACMessage, error)); ok {
@@ -85,6 +89,10 @@ func (_c *mockICBMHandler_ChannelMsgToHostHandler_Call) RunAndReturn(run func(co
 func (_m *mockICBMHandler) ClientEventHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x04_0x14_ICBMClientEvent) error {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ClientEventHandler")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x04_0x14_ICBMClientEvent) error); ok {
 		r0 = rf(ctx, sess, inFrame, inBody)
@@ -130,6 +138,10 @@ func (_c *mockICBMHandler_ClientEventHandler_Call) RunAndReturn(run func(context
 func (_m *mockICBMHandler) EvilRequestHandler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x04_0x08_ICBMEvilRequest) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for EvilRequestHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x04_0x08_ICBMEvilRequest) (oscar.SNACMessage, error)); ok {
@@ -185,6 +197,10 @@ func (_c *mockICBMHandler_EvilRequestHandler_Call) RunAndReturn(run func(context
 func (_m *mockICBMHandler) ParameterQueryHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, inFrame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ParameterQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, inFrame)

+ 2 - 2
server/locate.go

@@ -11,7 +11,7 @@ import (
 
 type LocateHandler interface {
 	RightsQueryHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage
-	SetDirInfoHandler(ctx context.Context) oscar.SNACMessage
+	SetDirInfoHandler(ctx context.Context, frame oscar.SNACFrame) oscar.SNACMessage
 	SetInfoHandler(ctx context.Context, sess *state.Session, inBody oscar.SNAC_0x02_0x04_LocateSetInfo) error
 	SetKeywordInfoHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage
 	UserInfoQuery2Handler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x02_0x15_LocateUserInfoQuery2) (oscar.SNACMessage, error)
@@ -49,7 +49,7 @@ func (rt LocateRouter) RouteLocate(ctx context.Context, sess *state.Session, inF
 		if err := oscar.Unmarshal(&inBody, r); err != nil {
 			return err
 		}
-		outSNAC := rt.SetDirInfoHandler(ctx)
+		outSNAC := rt.SetDirInfoHandler(ctx, inFrame)
 		rt.logRequestAndResponse(ctx, inFrame, inBody, outSNAC.Frame, outSNAC.Body)
 		return sendSNAC(outSNAC.Frame, outSNAC.Body, sequence, w)
 	case oscar.LocateGetDirInfo:

+ 32 - 11
server/locate_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockLocateHandler) EXPECT() *mockLocateHandler_Expecter {
 func (_m *mockLocateHandler) RightsQueryHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, inFrame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RightsQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, inFrame)
@@ -67,13 +71,17 @@ func (_c *mockLocateHandler_RightsQueryHandler_Call) RunAndReturn(run func(conte
 	return _c
 }
 
-// SetDirInfoHandler provides a mock function with given fields: ctx
-func (_m *mockLocateHandler) SetDirInfoHandler(ctx context.Context) oscar.SNACMessage {
-	ret := _m.Called(ctx)
+// SetDirInfoHandler provides a mock function with given fields: ctx, frame
+func (_m *mockLocateHandler) SetDirInfoHandler(ctx context.Context, frame oscar.SNACFrame) oscar.SNACMessage {
+	ret := _m.Called(ctx, frame)
+
+	if len(ret) == 0 {
+		panic("no return value specified for SetDirInfoHandler")
+	}
 
 	var r0 oscar.SNACMessage
-	if rf, ok := ret.Get(0).(func(context.Context) oscar.SNACMessage); ok {
-		r0 = rf(ctx)
+	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
+		r0 = rf(ctx, frame)
 	} else {
 		r0 = ret.Get(0).(oscar.SNACMessage)
 	}
@@ -88,13 +96,14 @@ type mockLocateHandler_SetDirInfoHandler_Call struct {
 
 // SetDirInfoHandler is a helper method to define mock.On call
 //   - ctx context.Context
-func (_e *mockLocateHandler_Expecter) SetDirInfoHandler(ctx interface{}) *mockLocateHandler_SetDirInfoHandler_Call {
-	return &mockLocateHandler_SetDirInfoHandler_Call{Call: _e.mock.On("SetDirInfoHandler", ctx)}
+//   - frame oscar.SNACFrame
+func (_e *mockLocateHandler_Expecter) SetDirInfoHandler(ctx interface{}, frame interface{}) *mockLocateHandler_SetDirInfoHandler_Call {
+	return &mockLocateHandler_SetDirInfoHandler_Call{Call: _e.mock.On("SetDirInfoHandler", ctx, frame)}
 }
 
-func (_c *mockLocateHandler_SetDirInfoHandler_Call) Run(run func(ctx context.Context)) *mockLocateHandler_SetDirInfoHandler_Call {
+func (_c *mockLocateHandler_SetDirInfoHandler_Call) Run(run func(ctx context.Context, frame oscar.SNACFrame)) *mockLocateHandler_SetDirInfoHandler_Call {
 	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context))
+		run(args[0].(context.Context), args[1].(oscar.SNACFrame))
 	})
 	return _c
 }
@@ -104,7 +113,7 @@ func (_c *mockLocateHandler_SetDirInfoHandler_Call) Return(_a0 oscar.SNACMessage
 	return _c
 }
 
-func (_c *mockLocateHandler_SetDirInfoHandler_Call) RunAndReturn(run func(context.Context) oscar.SNACMessage) *mockLocateHandler_SetDirInfoHandler_Call {
+func (_c *mockLocateHandler_SetDirInfoHandler_Call) RunAndReturn(run func(context.Context, oscar.SNACFrame) oscar.SNACMessage) *mockLocateHandler_SetDirInfoHandler_Call {
 	_c.Call.Return(run)
 	return _c
 }
@@ -113,6 +122,10 @@ func (_c *mockLocateHandler_SetDirInfoHandler_Call) RunAndReturn(run func(contex
 func (_m *mockLocateHandler) SetInfoHandler(ctx context.Context, sess *state.Session, inBody oscar.SNAC_0x02_0x04_LocateSetInfo) error {
 	ret := _m.Called(ctx, sess, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for SetInfoHandler")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNAC_0x02_0x04_LocateSetInfo) error); ok {
 		r0 = rf(ctx, sess, inBody)
@@ -157,6 +170,10 @@ func (_c *mockLocateHandler_SetInfoHandler_Call) RunAndReturn(run func(context.C
 func (_m *mockLocateHandler) SetKeywordInfoHandler(ctx context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, inFrame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for SetKeywordInfoHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, inFrame)
@@ -200,6 +217,10 @@ func (_c *mockLocateHandler_SetKeywordInfoHandler_Call) RunAndReturn(run func(co
 func (_m *mockLocateHandler) UserInfoQuery2Handler(ctx context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x02_0x15_LocateUserInfoQuery2) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, inFrame, inBody)
 
+	if len(ret) == 0 {
+		panic("no return value specified for UserInfoQuery2Handler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x02_0x15_LocateUserInfoQuery2) (oscar.SNACMessage, error)); ok {

+ 1 - 1
server/locate_test.go

@@ -191,7 +191,7 @@ func TestLocateRouter_RouteLocate(t *testing.T) {
 				Return(tc.output).
 				Maybe()
 			svc.EXPECT().
-				SetDirInfoHandler(mock.Anything).
+				SetDirInfoHandler(mock.Anything, tc.input.Frame).
 				Return(tc.output).
 				Maybe()
 			svc.EXPECT().

+ 33 - 1
server/oservice_bos_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockOServiceBOSHandler) EXPECT() *mockOServiceBOSHandler_Expecter {
 func (_m *mockOServiceBOSHandler) ClientOnlineHandler(ctx context.Context, bodyIn oscar.SNAC_0x01_0x02_OServiceClientOnline, sess *state.Session) error {
 	ret := _m.Called(ctx, bodyIn, sess)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ClientOnlineHandler")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNAC_0x01_0x02_OServiceClientOnline, *state.Session) error); ok {
 		r0 = rf(ctx, bodyIn, sess)
@@ -72,6 +76,10 @@ func (_c *mockOServiceBOSHandler_ClientOnlineHandler_Call) RunAndReturn(run func
 func (_m *mockOServiceBOSHandler) ClientVersionsHandler(ctx context.Context, frame oscar.SNACFrame, bodyIn oscar.SNAC_0x01_0x17_OServiceClientVersions) oscar.SNACMessage {
 	ret := _m.Called(ctx, frame, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ClientVersionsHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame, oscar.SNAC_0x01_0x17_OServiceClientVersions) oscar.SNACMessage); ok {
 		r0 = rf(ctx, frame, bodyIn)
@@ -116,6 +124,10 @@ func (_c *mockOServiceBOSHandler_ClientVersionsHandler_Call) RunAndReturn(run fu
 func (_m *mockOServiceBOSHandler) IdleNotificationHandler(ctx context.Context, sess *state.Session, bodyIn oscar.SNAC_0x01_0x11_OServiceIdleNotification) error {
 	ret := _m.Called(ctx, sess, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for IdleNotificationHandler")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNAC_0x01_0x11_OServiceIdleNotification) error); ok {
 		r0 = rf(ctx, sess, bodyIn)
@@ -160,6 +172,10 @@ func (_c *mockOServiceBOSHandler_IdleNotificationHandler_Call) RunAndReturn(run
 func (_m *mockOServiceBOSHandler) RateParamsQueryHandler(ctx context.Context, frame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, frame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RateParamsQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, frame)
@@ -237,6 +253,10 @@ func (_c *mockOServiceBOSHandler_RateParamsSubAddHandler_Call) RunAndReturn(run
 func (_m *mockOServiceBOSHandler) ServiceRequestHandler(ctx context.Context, sess *state.Session, frame oscar.SNACFrame, bodyIn oscar.SNAC_0x01_0x04_OServiceServiceRequest) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, frame, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ServiceRequestHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x01_0x04_OServiceServiceRequest) (oscar.SNACMessage, error)); ok {
@@ -292,6 +312,10 @@ func (_c *mockOServiceBOSHandler_ServiceRequestHandler_Call) RunAndReturn(run fu
 func (_m *mockOServiceBOSHandler) SetUserInfoFieldsHandler(ctx context.Context, sess *state.Session, frame oscar.SNACFrame, bodyIn oscar.SNAC_0x01_0x1E_OServiceSetUserInfoFields) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, frame, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for SetUserInfoFieldsHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x01_0x1E_OServiceSetUserInfoFields) (oscar.SNACMessage, error)); ok {
@@ -347,6 +371,10 @@ func (_c *mockOServiceBOSHandler_SetUserInfoFieldsHandler_Call) RunAndReturn(run
 func (_m *mockOServiceBOSHandler) UserInfoQueryHandler(ctx context.Context, sess *state.Session, frame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, sess, frame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for UserInfoQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, sess, frame)
@@ -391,6 +419,10 @@ func (_c *mockOServiceBOSHandler_UserInfoQueryHandler_Call) RunAndReturn(run fun
 func (_m *mockOServiceBOSHandler) WriteOServiceHostOnline() oscar.SNACMessage {
 	ret := _m.Called()
 
+	if len(ret) == 0 {
+		panic("no return value specified for WriteOServiceHostOnline")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func() oscar.SNACMessage); ok {
 		r0 = rf()

+ 29 - 1
server/oservice_chat_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockOServiceChatHandler) EXPECT() *mockOServiceChatHandler_Expecter {
 func (_m *mockOServiceChatHandler) ClientOnlineHandler(ctx context.Context, sess *state.Session, chatID string) error {
 	ret := _m.Called(ctx, sess, chatID)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ClientOnlineHandler")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, string) error); ok {
 		r0 = rf(ctx, sess, chatID)
@@ -72,6 +76,10 @@ func (_c *mockOServiceChatHandler_ClientOnlineHandler_Call) RunAndReturn(run fun
 func (_m *mockOServiceChatHandler) ClientVersionsHandler(ctx context.Context, frame oscar.SNACFrame, bodyIn oscar.SNAC_0x01_0x17_OServiceClientVersions) oscar.SNACMessage {
 	ret := _m.Called(ctx, frame, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ClientVersionsHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame, oscar.SNAC_0x01_0x17_OServiceClientVersions) oscar.SNACMessage); ok {
 		r0 = rf(ctx, frame, bodyIn)
@@ -116,6 +124,10 @@ func (_c *mockOServiceChatHandler_ClientVersionsHandler_Call) RunAndReturn(run f
 func (_m *mockOServiceChatHandler) IdleNotificationHandler(ctx context.Context, sess *state.Session, bodyIn oscar.SNAC_0x01_0x11_OServiceIdleNotification) error {
 	ret := _m.Called(ctx, sess, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for IdleNotificationHandler")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNAC_0x01_0x11_OServiceIdleNotification) error); ok {
 		r0 = rf(ctx, sess, bodyIn)
@@ -160,6 +172,10 @@ func (_c *mockOServiceChatHandler_IdleNotificationHandler_Call) RunAndReturn(run
 func (_m *mockOServiceChatHandler) RateParamsQueryHandler(ctx context.Context, frame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, frame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RateParamsQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, frame)
@@ -237,6 +253,10 @@ func (_c *mockOServiceChatHandler_RateParamsSubAddHandler_Call) RunAndReturn(run
 func (_m *mockOServiceChatHandler) SetUserInfoFieldsHandler(ctx context.Context, sess *state.Session, frame oscar.SNACFrame, bodyIn oscar.SNAC_0x01_0x1E_OServiceSetUserInfoFields) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, frame, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for SetUserInfoFieldsHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x01_0x1E_OServiceSetUserInfoFields) (oscar.SNACMessage, error)); ok {
@@ -292,6 +312,10 @@ func (_c *mockOServiceChatHandler_SetUserInfoFieldsHandler_Call) RunAndReturn(ru
 func (_m *mockOServiceChatHandler) UserInfoQueryHandler(ctx context.Context, sess *state.Session, frame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, sess, frame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for UserInfoQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, sess, frame)
@@ -336,6 +360,10 @@ func (_c *mockOServiceChatHandler_UserInfoQueryHandler_Call) RunAndReturn(run fu
 func (_m *mockOServiceChatHandler) WriteOServiceHostOnline() oscar.SNACMessage {
 	ret := _m.Called()
 
+	if len(ret) == 0 {
+		panic("no return value specified for WriteOServiceHostOnline")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func() oscar.SNACMessage); ok {
 		r0 = rf()

+ 21 - 1
server/oservice_mock.go

@@ -1,4 +1,4 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
+// Code generated by mockery v2.38.0. DO NOT EDIT.
 
 package server
 
@@ -28,6 +28,10 @@ func (_m *mockOServiceHandler) EXPECT() *mockOServiceHandler_Expecter {
 func (_m *mockOServiceHandler) ClientVersionsHandler(ctx context.Context, frame oscar.SNACFrame, bodyIn oscar.SNAC_0x01_0x17_OServiceClientVersions) oscar.SNACMessage {
 	ret := _m.Called(ctx, frame, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for ClientVersionsHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame, oscar.SNAC_0x01_0x17_OServiceClientVersions) oscar.SNACMessage); ok {
 		r0 = rf(ctx, frame, bodyIn)
@@ -72,6 +76,10 @@ func (_c *mockOServiceHandler_ClientVersionsHandler_Call) RunAndReturn(run func(
 func (_m *mockOServiceHandler) IdleNotificationHandler(ctx context.Context, sess *state.Session, bodyIn oscar.SNAC_0x01_0x11_OServiceIdleNotification) error {
 	ret := _m.Called(ctx, sess, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for IdleNotificationHandler")
+	}
+
 	var r0 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNAC_0x01_0x11_OServiceIdleNotification) error); ok {
 		r0 = rf(ctx, sess, bodyIn)
@@ -116,6 +124,10 @@ func (_c *mockOServiceHandler_IdleNotificationHandler_Call) RunAndReturn(run fun
 func (_m *mockOServiceHandler) RateParamsQueryHandler(ctx context.Context, frame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, frame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for RateParamsQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, frame)
@@ -193,6 +205,10 @@ func (_c *mockOServiceHandler_RateParamsSubAddHandler_Call) RunAndReturn(run fun
 func (_m *mockOServiceHandler) SetUserInfoFieldsHandler(ctx context.Context, sess *state.Session, frame oscar.SNACFrame, bodyIn oscar.SNAC_0x01_0x1E_OServiceSetUserInfoFields) (oscar.SNACMessage, error) {
 	ret := _m.Called(ctx, sess, frame, bodyIn)
 
+	if len(ret) == 0 {
+		panic("no return value specified for SetUserInfoFieldsHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	var r1 error
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame, oscar.SNAC_0x01_0x1E_OServiceSetUserInfoFields) (oscar.SNACMessage, error)); ok {
@@ -248,6 +264,10 @@ func (_c *mockOServiceHandler_SetUserInfoFieldsHandler_Call) RunAndReturn(run fu
 func (_m *mockOServiceHandler) UserInfoQueryHandler(ctx context.Context, sess *state.Session, frame oscar.SNACFrame) oscar.SNACMessage {
 	ret := _m.Called(ctx, sess, frame)
 
+	if len(ret) == 0 {
+		panic("no return value specified for UserInfoQueryHandler")
+	}
+
 	var r0 oscar.SNACMessage
 	if rf, ok := ret.Get(0).(func(context.Context, *state.Session, oscar.SNACFrame) oscar.SNACMessage); ok {
 		r0 = rf(ctx, sess, frame)