403Webshell
Server IP : 157.230.181.24  /  Your IP : 216.73.217.11
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux conductive 6.8.0-117-generic #117-Ubuntu SMP PREEMPT_DYNAMIC Tue May 5 19:26:24 UTC 2026 x86_64
User :  ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/vhosts/ceagon/open-oscar-server/foodgroup/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/vhosts/ceagon/open-oscar-server/foodgroup/admin_test.go
package foodgroup

import (
	"context"
	"io"
	"log/slog"
	"net/mail"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"

	"github.com/mk6i/open-oscar-server/config"
	"github.com/mk6i/open-oscar-server/state"
	"github.com/mk6i/open-oscar-server/wire"
)

func TestAdminService_ConfirmRequest(t *testing.T) {
	cases := []struct {
		// name is the unit test name
		name string
		// cfg is the app configuration
		cfg config.Config
		// inputSNAC is the SNAC sent from the client to the server
		inputSNAC wire.SNACMessage
		// mockParams is the list of params sent to mocks that satisfy this
		// method's dependencies
		mockParams mockParams
		// instance is the session of the user
		instance *state.SessionInstance
		// expectOutput is the SNAC sent from the server to client
		expectOutput wire.SNACMessage
		// expectErr is the expected error returned
		expectErr error
	}{
		{
			name:     "unconfirmed account sends confirmation request",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminAcctConfirmRequest,
					RequestID: 1234,
				},
				Body: wire.SNAC_0x07_0x06_AdminConfirmRequest{},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminAcctConfirmReply,
					RequestID: 1234,
				},
				Body: wire.SNAC_0x07_0x07_AdminConfirmReply{
					Status: wire.AdminAcctConfirmStatusEmailSent,
				},
			},
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerEmailAddressParams: accountManagerEmailAddressParams{
						{

							screenName: state.NewIdentScreenName("chattingchuck"),
							emailAddress: &mail.Address{
								Address: "chuck@aol.com",
							},
							err: nil,
						},
					},
					accountManagerConfirmStatusParams: accountManagerConfirmStatusParams{
						{
							screenName:    state.NewIdentScreenName("chattingchuck"),
							confirmStatus: false,
							err:           nil,
						},
					},
					accountManagerUpdateConfirmStatusParams: accountManagerUpdateConfirmStatusParams{
						{
							confirmStatus: true,
							screenName:    state.NewIdentScreenName("chattingchuck"),
							err:           nil,
						},
					},
				},
				buddyBroadcasterParams: buddyBroadcasterParams{
					broadcastBuddyArrivedParams: broadcastBuddyArrivedParams{
						{
							screenName: state.DisplayScreenName("Chatting Chuck"),
						},
					},
				},
			},
		},
		{
			name:     "already confirmed account sends confirmation request",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminAcctConfirmRequest,
					RequestID: 1234,
				},
				Body: wire.SNAC_0x07_0x06_AdminConfirmRequest{},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminAcctConfirmReply,
					RequestID: 1234,
				},
				Body: wire.SNAC_0x07_0x07_AdminConfirmReply{
					Status: wire.AdminAcctConfirmStatusAlreadyConfirmed,
				},
			},
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerEmailAddressParams: accountManagerEmailAddressParams{
						{

							screenName: state.NewIdentScreenName("chattingchuck"),
							emailAddress: &mail.Address{
								Address: "chuck@aol.com",
							},
							err: nil,
						},
					},
					accountManagerConfirmStatusParams: accountManagerConfirmStatusParams{
						{
							screenName:    state.NewIdentScreenName("chattingchuck"),
							confirmStatus: true,
							err:           nil,
						},
					},
				},
			},
		},
		{
			name:     "acccount with no email address sends confirmation request",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminAcctConfirmRequest,
					RequestID: 1234,
				},
				Body: wire.SNAC_0x07_0x06_AdminConfirmRequest{},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminAcctConfirmReply,
					RequestID: 1234,
				},
				Body: wire.SNAC_0x07_0x07_AdminConfirmReply{
					Status: wire.AdminAcctConfirmStatusServerError,
				},
			},
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerEmailAddressParams: accountManagerEmailAddressParams{
						{

							screenName:   state.NewIdentScreenName("chattingchuck"),
							emailAddress: nil,
							err:          state.ErrNoEmailAddress,
						},
					},
				},
			},
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			messageRelayer := newMockMessageRelayer(t)
			accountManager := newMockAccountManager(t)
			buddyBroadcaster := newMockbuddyBroadcaster(t)

			for _, params := range tc.mockParams.accountManagerEmailAddressParams {
				accountManager.EXPECT().
					EmailAddress(matchContext(), params.screenName).
					Return(params.emailAddress, params.err)
			}
			for _, params := range tc.mockParams.accountManagerConfirmStatusParams {
				accountManager.EXPECT().
					ConfirmStatus(matchContext(), params.screenName).
					Return(params.confirmStatus, params.err)
			}
			for _, params := range tc.mockParams.accountManagerUpdateConfirmStatusParams {
				accountManager.EXPECT().
					UpdateConfirmStatus(matchContext(), params.screenName, params.confirmStatus).
					Return(params.err)
			}
			for _, params := range tc.mockParams.broadcastBuddyArrivedParams {
				buddyBroadcaster.EXPECT().
					BroadcastBuddyArrived(mock.Anything, tc.instance.IdentScreenName(), tc.instance.Session().TLVUserInfo()).
					Return(params.err)
			}
			svc := AdminService{
				messageRelayer:   messageRelayer,
				accountManager:   accountManager,
				buddyBroadcaster: buddyBroadcaster,
			}
			outputSNAC, err := svc.ConfirmRequest(context.Background(), tc.instance, tc.inputSNAC.Frame)
			assert.ErrorIs(t, err, tc.expectErr)
			if tc.expectErr != nil {
				return
			}
			assert.Equal(t, tc.expectOutput, outputSNAC)
		})
	}
}

func TestAdminService_InfoQuery(t *testing.T) {
	cases := []struct {
		// name is the unit test name
		name string
		// cfg is the app configuration
		cfg config.Config
		// inputSNAC is the SNAC sent from the client to the server
		inputSNAC wire.SNACMessage
		// mockParams is the list of params sent to mocks that satisfy this
		// method's dependencies
		mockParams mockParams
		// instance is the session of the user
		instance *state.SessionInstance
		// expectOutput is the SNAC sent from the server to client
		expectOutput wire.SNACMessage
		// expectErr is the expected error returned
		expectErr error
	}{
		{
			name:     "user requests account registration status",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoQuery,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVRegistrationStatus, uint16(0x00))},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x03_AdminInfoReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusLimitDisclosure),
						},
					},
				},
			},
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerRegStatusParams: accountManagerRegStatusParams{
						{
							screenName: state.NewIdentScreenName("chattingchuck"),
							regStatus:  wire.AdminInfoRegStatusLimitDisclosure,
							err:        nil,
						},
					},
				},
			},
		},
		{
			name:     "user requests account email address",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoQuery,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, uint16(0x00))},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x03_AdminInfoReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"),
						},
					},
				},
			},
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerEmailAddressParams: accountManagerEmailAddressParams{
						{
							screenName: state.NewIdentScreenName("chattingchuck"),
							emailAddress: &mail.Address{
								Address: "chattingchuck@aol.com",
							},
							err: nil,
						},
					},
				},
			},
		},
		{
			name:     "user requests account email address but not set",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoQuery,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, uint16(0x00))},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x03_AdminInfoReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, ""),
						},
					},
				},
			},
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerEmailAddressParams: accountManagerEmailAddressParams{
						{
							screenName:   state.NewIdentScreenName("chattingchuck"),
							emailAddress: nil,
							err:          state.ErrNoEmailAddress,
						},
					},
				},
			},
		},
		{
			name:     "user requests formatted screenname",
			instance: newTestInstance("ChattingChuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoQuery,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, uint16(0x00))},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x03_AdminInfoReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "ChattingChuck"),
						},
					},
				},
			},
		},
		{
			name:     "user requests invalid TLV",
			instance: newTestInstance("ChattingChuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoQuery,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x02_AdminInfoQuery{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(uint16(0x99), uint16(0x00))},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminErr,
					RequestID: 1337,
				},
				Body: wire.SNACError{
					Code: wire.ErrorCodeNotSupportedByHost,
				},
			},
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			messageRelayer := newMockMessageRelayer(t)
			accountManager := newMockAccountManager(t)
			buddyBroadcaster := newMockbuddyBroadcaster(t)

			for _, params := range tc.mockParams.accountManagerRegStatusParams {
				accountManager.EXPECT().
					RegStatus(matchContext(), params.screenName).
					Return(params.regStatus, params.err)
			}

			for _, params := range tc.mockParams.accountManagerEmailAddressParams {
				accountManager.EXPECT().
					EmailAddress(matchContext(), params.screenName).
					Return(params.emailAddress, params.err)
			}

			svc := AdminService{
				messageRelayer:   messageRelayer,
				accountManager:   accountManager,
				buddyBroadcaster: buddyBroadcaster,
			}
			outputSNAC, err := svc.InfoQuery(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x02_AdminInfoQuery))
			assert.ErrorIs(t, err, tc.expectErr)
			if tc.expectErr != nil {
				return
			}
			assert.Equal(t, tc.expectOutput, outputSNAC)
		})
	}
}

func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) {
	cases := []struct {
		// name is the unit test name
		name string
		// cfg is the app configuration
		cfg config.Config
		// inputSNAC is the SNAC sent from the client to the server
		inputSNAC wire.SNACMessage
		// mockParams is the list of params sent to mocks that satisfy this
		// method's dependencies
		mockParams mockParams
		// instance is the session of the user
		instance *state.SessionInstance
		// expectOutput is the SNAC sent from the server to client
		expectOutput wire.SNACMessage
		// expectErr is the expected error returned
		expectErr error
	}{
		{
			name:     "user changes screen name format successfully aim < 6",
			instance: newTestInstance("chattingchuck"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerUpdateDisplayScreenNameParams: accountManagerUpdateDisplayScreenNameParams{
						{
							displayScreenName: state.DisplayScreenName("Chatting Chuck"),
						},
					},
				},
				buddyBroadcasterParams: buddyBroadcasterParams{
					broadcastBuddyArrivedParams: broadcastBuddyArrivedParams{
						{
							screenName: state.DisplayScreenName("Chatting Chuck"),
						},
					},
				},
				messageRelayerParams: messageRelayerParams{
					relayToScreenNameParams: relayToScreenNameParams{
						{
							screenName: state.NewIdentScreenName("Chatting Chuck"),
							message: wire.SNACMessage{
								Frame: wire.SNACFrame{
									FoodGroup: wire.OService,
									SubGroup:  wire.OServiceUserInfoUpdate,
								},
								Body: newOServiceUserInfoUpdate(newTestInstance("Chatting Chuck")),
							},
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
						},
					},
				},
			},
		},
		{
			name:     "user changes screen name format successfully aim >= 6",
			instance: newTestInstance("chattingchuck", sessOptSetFoodGroupVersion(wire.OService, 4)),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerUpdateDisplayScreenNameParams: accountManagerUpdateDisplayScreenNameParams{
						{
							displayScreenName: state.DisplayScreenName("Chatting Chuck"),
						},
					},
				},
				buddyBroadcasterParams: buddyBroadcasterParams{
					broadcastBuddyArrivedParams: broadcastBuddyArrivedParams{
						{
							screenName: state.DisplayScreenName("Chatting Chuck"),
						},
					},
				},
				messageRelayerParams: messageRelayerParams{
					relayToScreenNameParams: relayToScreenNameParams{
						{
							screenName: state.NewIdentScreenName("Chatting Chuck"),
							message: wire.SNACMessage{
								Frame: wire.SNACFrame{
									FoodGroup: wire.OService,
									SubGroup:  wire.OServiceUserInfoUpdate,
								},
								Body: newOServiceUserInfoUpdate(newTestInstance("Chatting Chuck", sessOptSetFoodGroupVersion(wire.OService, 4))),
							},
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"),
						},
					},
				},
			},
		},
		{
			name:     "proposed screen name is too long",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "c  h  a  t  t  i  n  g  c  h  u  c  k")},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickNameLength),
							wire.NewTLVBE(wire.AdminTLVUrl, ""),
						},
					},
				},
			},
		},
		{
			name:     "proposed screen name does not match session screen name",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "QuietQuinton")},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorValidateNickName),
							wire.NewTLVBE(wire.AdminTLVUrl, ""),
						},
					},
				},
			},
		},
		{
			name:     "proposed screen name ends in a space",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "ChattingChuck ")},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickName),
							wire.NewTLVBE(wire.AdminTLVUrl, ""),
						},
					},
				},
			},
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			messageRelayer := newMockMessageRelayer(t)
			accountManager := newMockAccountManager(t)
			mockBuddyBroadcaster := newMockbuddyBroadcaster(t)

			for _, params := range tc.mockParams.accountManagerUpdateDisplayScreenNameParams {
				accountManager.EXPECT().
					UpdateDisplayScreenName(matchContext(), params.displayScreenName).
					Return(params.err)
			}

			for _, params := range tc.mockParams.broadcastBuddyArrivedParams {
				mockBuddyBroadcaster.EXPECT().
					BroadcastBuddyArrived(mock.Anything, state.NewIdentScreenName(params.screenName.String()), mock.MatchedBy(func(userInfo wire.TLVUserInfo) bool {
						return userInfo.ScreenName == params.screenName.String()
					})).
					Return(params.err)
			}

			for _, params := range tc.mockParams.relayToScreenNameParams {
				p := params
				messageRelayer.EXPECT().
					RelayToScreenName(mock.Anything, p.screenName, p.message)
			}

			svc := AdminService{
				accountManager:   accountManager,
				buddyBroadcaster: mockBuddyBroadcaster,
				messageRelayer:   messageRelayer,
			}
			outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
			assert.ErrorIs(t, err, tc.expectErr)
			if tc.expectErr != nil {
				return
			}
			assert.Equal(t, tc.expectOutput, outputSNAC)
		})
	}
}

func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) {
	// One case needs a 320 character long email address
	longEmailAddress := "longemailaddress@"
	for i := 0; i < 50; i++ {
		longEmailAddress += "domain"
	}
	longEmailAddress += ".com"
	cases := []struct {
		// name is the unit test name
		name string
		// cfg is the app configuration
		cfg config.Config
		// inputSNAC is the SNAC sent from the client to the server
		inputSNAC wire.SNACMessage
		// mockParams is the list of params sent to mocks that satisfy this
		// method's dependencies
		mockParams mockParams
		// instance is the session of the user
		instance *state.SessionInstance
		// expectOutput is the SNAC sent from the server to client
		expectOutput wire.SNACMessage
		// expectErr is the expected error returned
		expectErr error
	}{
		{
			name:     "user changes email address successfully",
			instance: newTestInstance("chattingchuck"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerUpdateEmailAddressParams: accountManagerUpdateEmailAddressParams{
						{
							screenName: state.NewIdentScreenName("chattingchuck"),
							emailAddress: &mail.Address{
								Address: "chattingchuck@aol.com",
							},
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"),
						},
					},
				},
			},
		},
		{
			name:     "proposed email address invalid rfc 5322 format",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@@@@@@@aol.com"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmail),
							wire.NewTLVBE(wire.AdminTLVUrl, ""),
						},
					},
				},
			},
		},
		{
			name:     "proposed email address too long",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVEmailAddress, longEmailAddress),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmailLength),
							wire.NewTLVBE(wire.AdminTLVUrl, ""),
						},
					},
				},
			},
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			messageRelayer := newMockMessageRelayer(t)
			accountManager := newMockAccountManager(t)
			buddyBroadcaster := newMockbuddyBroadcaster(t)

			for _, params := range tc.mockParams.accountManagerUpdateEmailAddressParams {
				accountManager.EXPECT().
					UpdateEmailAddress(matchContext(), params.screenName, params.emailAddress).
					Return(params.err)
			}

			svc := AdminService{
				accountManager:   accountManager,
				buddyBroadcaster: buddyBroadcaster,
				messageRelayer:   messageRelayer,
			}
			outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
			assert.ErrorIs(t, err, tc.expectErr)
			if tc.expectErr != nil {
				return
			}
			assert.Equal(t, tc.expectOutput, outputSNAC)
		})
	}
}

func TestAdminService_InfoChangeRequest_RegStatus(t *testing.T) {
	cases := []struct {
		// name is the unit test name
		name string
		// cfg is the app configuration
		cfg config.Config
		// inputSNAC is the SNAC sent from the client to the server
		inputSNAC wire.SNACMessage
		// mockParams is the list of params sent to mocks that satisfy this
		// method's dependencies
		mockParams mockParams
		// instance is the session of the user
		instance *state.SessionInstance
		// expectOutput is the SNAC sent from the server to client
		expectOutput wire.SNACMessage
		// expectErr is the expected error returned
		expectErr error
	}{
		{
			name:     "user changes reg preference successfully",
			instance: newTestInstance("chattingchuck"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerUpdateRegStatusParams: accountManagerUpdateRegStatusParams{
						{
							screenName: state.NewIdentScreenName("chattingchuck"),
							regStatus:  wire.AdminInfoRegStatusNoDisclosure,
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure),
						},
					},
				},
			},
		},
		{
			name:     "proposed reg preference invalid",
			instance: newTestInstance("chattingchuck"),
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVRegistrationStatus, uint16(0x1337)),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidRegistrationPreference),
							wire.NewTLVBE(wire.AdminTLVUrl, ""),
						},
					},
				},
			},
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			messageRelayer := newMockMessageRelayer(t)
			accountManager := newMockAccountManager(t)
			buddyBroadcaster := newMockbuddyBroadcaster(t)

			for _, params := range tc.mockParams.accountManagerUpdateRegStatusParams {
				accountManager.EXPECT().
					UpdateRegStatus(context.Background(), params.screenName, params.regStatus).
					Return(params.err)
			}

			svc := AdminService{
				accountManager:   accountManager,
				buddyBroadcaster: buddyBroadcaster,
				messageRelayer:   messageRelayer,
			}
			outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
			assert.ErrorIs(t, err, tc.expectErr)
			if tc.expectErr != nil {
				return
			}
			assert.Equal(t, tc.expectOutput, outputSNAC)
		})
	}
}

func TestAdminService_InfoChangeRequest_Password(t *testing.T) {
	cases := []struct {
		// name is the unit test name
		name string
		// cfg is the app configuration
		cfg config.Config
		// inputSNAC is the SNAC sent from the client to the server
		inputSNAC wire.SNACMessage
		// mockParams is the list of params sent to mocks that satisfy this
		// method's dependencies
		mockParams mockParams
		// instance is the session of the user
		instance *state.SessionInstance
		// expectOutput is the SNAC sent from the server to client
		expectOutput wire.SNACMessage
		// expectErr is the expected error returned
		expectErr error
	}{
		{
			name:     "user changes password successfully",
			instance: newTestInstance("me"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerSetUserPasswordParams: accountManagerSetUserPasswordParams{
						{
							screenName: state.NewIdentScreenName("me"),
							password:   "newpass",
						},
					},
					accountManagerUserParams: accountManagerUserParams{
						{
							screenName: state.NewIdentScreenName("me"),
							result: func() *state.User {
								user := &state.User{
									AuthKey: "auth_key",
								}
								assert.NoError(t, user.HashPassword("oldpass"))
								return user
							}(),
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
							wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
						},
					},
				},
			},
		},
		{
			name:     "user changes password, invalid new password length",
			instance: newTestInstance("me"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerSetUserPasswordParams: accountManagerSetUserPasswordParams{
						{
							screenName: state.NewIdentScreenName("me"),
							password:   "newpass",
							err:        state.ErrPasswordInvalid,
						},
					},
					accountManagerUserParams: accountManagerUserParams{
						{
							screenName: state.NewIdentScreenName("me"),
							result: func() *state.User {
								user := &state.User{
									AuthKey: "auth_key",
								}
								assert.NoError(t, user.HashPassword("oldpass"))
								return user
							}(),
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
							wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidPasswordLength),
						},
					},
				},
			},
		},
		{
			name:     "user changes password, set user password runtime error",
			instance: newTestInstance("me"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerSetUserPasswordParams: accountManagerSetUserPasswordParams{
						{
							screenName: state.NewIdentScreenName("me"),
							password:   "newpass",
							err:        io.EOF,
						},
					},
					accountManagerUserParams: accountManagerUserParams{
						{
							screenName: state.NewIdentScreenName("me"),
							result: func() *state.User {
								user := &state.User{
									AuthKey: "auth_key",
								}
								assert.NoError(t, user.HashPassword("oldpass"))
								return user
							}(),
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
							wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorAllOtherErrors),
						},
					},
				},
			},
		},
		{
			name:     "user changes password, old password is invalid",
			instance: newTestInstance("me"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerUserParams: accountManagerUserParams{
						{
							screenName: state.NewIdentScreenName("me"),
							result: func() *state.User {
								user := &state.User{
									AuthKey: "auth_key",
								}
								assert.NoError(t, user.HashPassword("oldpass"))
								return user
							}(),
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpassbad"),
							wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorValidatePassword),
						},
					},
				},
			},
		},
		{
			name:     "user changes password, user not found",
			instance: newTestInstance("me"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerUserParams: accountManagerUserParams{
						{
							screenName: state.NewIdentScreenName("me"),
							result:     nil,
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
							wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorAllOtherErrors),
						},
					},
				},
			},
		},
		{
			name:     "user changes password, user lookup runtime error",
			instance: newTestInstance("me"),
			mockParams: mockParams{
				accountManagerParams: accountManagerParams{
					accountManagerUserParams: accountManagerUserParams{
						{
							screenName: state.NewIdentScreenName("me"),
							err:        io.EOF,
						},
					},
				},
			},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVOldPassword, "oldpass"),
							wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorAllOtherErrors),
						},
					},
				},
			},
		},
		{
			name:       "user changes password, missing old password",
			instance:   newTestInstance("me"),
			mockParams: mockParams{},
			inputSNAC: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeRequest,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{
					TLVRestBlock: wire.TLVRestBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, "newpass"),
						},
					},
				},
			},
			expectOutput: wire.SNACMessage{
				Frame: wire.SNACFrame{
					FoodGroup: wire.Admin,
					SubGroup:  wire.AdminInfoChangeReply,
					RequestID: 1337,
				},
				Body: wire.SNAC_0x07_0x05_AdminChangeReply{
					Permissions: wire.AdminInfoPermissionsReadWrite,
					TLVBlock: wire.TLVBlock{
						TLVList: wire.TLVList{
							wire.NewTLVBE(wire.AdminTLVNewPassword, []byte{}),
							wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorNeedOldPassword),
						},
					},
				},
			},
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			accountManager := newMockAccountManager(t)
			for _, params := range tc.mockParams.accountManagerUserParams {
				accountManager.EXPECT().
					User(matchContext(), params.screenName).
					Return(params.result, params.err)
			}
			for _, params := range tc.mockParams.accountManagerSetUserPasswordParams {
				accountManager.EXPECT().
					SetUserPassword(matchContext(), params.screenName, params.password).
					Return(params.err)
			}

			svc := AdminService{
				accountManager: accountManager,
				logger:         slog.Default(),
			}
			outputSNAC, err := svc.InfoChangeRequest(context.Background(), tc.instance, tc.inputSNAC.Frame, tc.inputSNAC.Body.(wire.SNAC_0x07_0x04_AdminInfoChangeRequest))
			assert.ErrorIs(t, err, tc.expectErr)
			if tc.expectErr != nil {
				return
			}
			assert.Equal(t, tc.expectOutput, outputSNAC)
		})
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit