2626import org .mockito .ArgumentCaptor ;
2727import org .mockito .Mock ;
2828import org .mockito .MockitoAnnotations ;
29+ import org .opensearch .ResourceNotFoundException ;
2930import org .opensearch .action .ActionListener ;
3031import org .opensearch .action .bulk .BulkItemResponse ;
3132import org .opensearch .action .delete .DeleteResponse ;
33+ import org .opensearch .action .get .GetResponse ;
3234import org .opensearch .action .support .ActionFilters ;
3335import org .opensearch .client .Client ;
36+ import org .opensearch .common .bytes .BytesReference ;
3437import org .opensearch .common .settings .Settings ;
3538import org .opensearch .common .util .concurrent .ThreadContext ;
39+ import org .opensearch .common .xcontent .NamedXContentRegistry ;
40+ import org .opensearch .common .xcontent .ToXContent ;
41+ import org .opensearch .common .xcontent .XContentBuilder ;
42+ import org .opensearch .common .xcontent .XContentFactory ;
43+ import org .opensearch .index .get .GetResult ;
3644import org .opensearch .index .reindex .BulkByScrollResponse ;
3745import org .opensearch .index .reindex .ScrollableHitSource ;
46+ import org .opensearch .ml .common .MLModel ;
47+ import org .opensearch .ml .common .model .MLModelState ;
3848import org .opensearch .ml .common .transport .model .MLModelDeleteRequest ;
3949import org .opensearch .test .OpenSearchTestCase ;
4050import org .opensearch .threadpool .ThreadPool ;
@@ -62,27 +72,31 @@ public class DeleteModelTransportActionTests extends OpenSearchTestCase {
6272 @ Mock
6373 BulkByScrollResponse bulkByScrollResponse ;
6474
75+ @ Mock
76+ NamedXContentRegistry xContentRegistry ;
77+
6578 @ Rule
6679 public ExpectedException exceptionRule = ExpectedException .none ();
6780
6881 DeleteModelTransportAction deleteModelTransportAction ;
6982 MLModelDeleteRequest mlModelDeleteRequest ;
7083 ThreadContext threadContext ;
84+ MLModel model ;
7185
7286 @ Before
7387 public void setup () throws IOException {
7488 MockitoAnnotations .openMocks (this );
7589
7690 mlModelDeleteRequest = MLModelDeleteRequest .builder ().modelId ("test_id" ).build ();
77- deleteModelTransportAction = spy (new DeleteModelTransportAction (transportService , actionFilters , client ));
91+ deleteModelTransportAction = spy (new DeleteModelTransportAction (transportService , actionFilters , client , xContentRegistry ));
7892
7993 Settings settings = Settings .builder ().build ();
8094 threadContext = new ThreadContext (settings );
8195 when (client .threadPool ()).thenReturn (threadPool );
8296 when (threadPool .getThreadContext ()).thenReturn (threadContext );
8397 }
8498
85- public void testDeleteModel_Success () {
99+ public void testDeleteModel_Success () throws IOException {
86100 doAnswer (invocation -> {
87101 ActionListener <DeleteResponse > listener = invocation .getArgument (1 );
88102 listener .onResponse (deleteResponse );
@@ -96,10 +110,74 @@ public void testDeleteModel_Success() {
96110 return null ;
97111 }).when (client ).execute (any (), any (), any ());
98112
113+ GetResponse getResponse = prepareMLModel (MLModelState .UPLOADED );
114+ doAnswer (invocation -> {
115+ ActionListener <GetResponse > actionListener = invocation .getArgument (1 );
116+ actionListener .onResponse (getResponse );
117+ return null ;
118+ }).when (client ).get (any (), any ());
119+
99120 deleteModelTransportAction .doExecute (null , mlModelDeleteRequest , actionListener );
100121 verify (actionListener ).onResponse (deleteResponse );
101122 }
102123
124+ public void testDeleteModel_CheckModelState () throws IOException {
125+ GetResponse getResponse = prepareMLModel (MLModelState .LOADING );
126+ doAnswer (invocation -> {
127+ ActionListener <GetResponse > actionListener = invocation .getArgument (1 );
128+ actionListener .onResponse (getResponse );
129+ return null ;
130+ }).when (client ).get (any (), any ());
131+
132+ deleteModelTransportAction .doExecute (null , mlModelDeleteRequest , actionListener );
133+ ArgumentCaptor <Exception > argumentCaptor = ArgumentCaptor .forClass (Exception .class );
134+ verify (actionListener ).onFailure (argumentCaptor .capture ());
135+ assertEquals (
136+ "Model cannot be deleted in loading or loaded state. Try unloading first and then delete" ,
137+ argumentCaptor .getValue ().getMessage ()
138+ );
139+ }
140+
141+ public void testDeleteModel_ModelNotFoundException () throws IOException {
142+ doAnswer (invocation -> {
143+ ActionListener <GetResponse > actionListener = invocation .getArgument (1 );
144+ actionListener .onFailure (new Exception ());
145+ return null ;
146+ }).when (client ).get (any (), any ());
147+
148+ deleteModelTransportAction .doExecute (null , mlModelDeleteRequest , actionListener );
149+ ArgumentCaptor <Exception > argumentCaptor = ArgumentCaptor .forClass (Exception .class );
150+ verify (actionListener ).onFailure (argumentCaptor .capture ());
151+ assertEquals ("Fail to find model" , argumentCaptor .getValue ().getMessage ());
152+ }
153+
154+ public void testDeleteModel_ResourceNotFoundException () throws IOException {
155+ doAnswer (invocation -> {
156+ ActionListener <DeleteResponse > listener = invocation .getArgument (1 );
157+ listener .onFailure (new ResourceNotFoundException ("errorMessage" ));
158+ return null ;
159+ }).when (client ).delete (any (), any ());
160+
161+ doAnswer (invocation -> {
162+ ActionListener <BulkByScrollResponse > listener = invocation .getArgument (2 );
163+ BulkByScrollResponse response = new BulkByScrollResponse (new ArrayList <>(), null );
164+ listener .onResponse (response );
165+ return null ;
166+ }).when (client ).execute (any (), any (), any ());
167+
168+ GetResponse getResponse = prepareMLModel (MLModelState .UPLOADED );
169+ doAnswer (invocation -> {
170+ ActionListener <GetResponse > actionListener = invocation .getArgument (1 );
171+ actionListener .onResponse (getResponse );
172+ return null ;
173+ }).when (client ).get (any (), any ());
174+
175+ deleteModelTransportAction .doExecute (null , mlModelDeleteRequest , actionListener );
176+ ArgumentCaptor <ResourceNotFoundException > argumentCaptor = ArgumentCaptor .forClass (ResourceNotFoundException .class );
177+ verify (actionListener ).onFailure (argumentCaptor .capture ());
178+ assertEquals ("errorMessage" , argumentCaptor .getValue ().getMessage ());
179+ }
180+
103181 public void testDeleteModelChunks_Success () {
104182 when (bulkByScrollResponse .getBulkFailures ()).thenReturn (null );
105183 doAnswer (invocation -> {
@@ -112,7 +190,14 @@ public void testDeleteModelChunks_Success() {
112190 verify (actionListener ).onResponse (deleteResponse );
113191 }
114192
115- public void testDeleteModel_RuntimeException () {
193+ public void testDeleteModel_RuntimeException () throws IOException {
194+ GetResponse getResponse = prepareMLModel (MLModelState .UPLOADED );
195+ doAnswer (invocation -> {
196+ ActionListener <GetResponse > actionListener = invocation .getArgument (1 );
197+ actionListener .onResponse (getResponse );
198+ return null ;
199+ }).when (client ).get (any (), any ());
200+
116201 doAnswer (invocation -> {
117202 ActionListener <DeleteResponse > listener = invocation .getArgument (1 );
118203 listener .onFailure (new RuntimeException ("errorMessage" ));
@@ -198,4 +283,13 @@ public void test_FailToDeleteAllModelChunks_SearchFailure() {
198283 verify (actionListener ).onFailure (argumentCaptor .capture ());
199284 assertEquals (OS_STATUS_EXCEPTION_MESSAGE + ", " + SEARCH_FAILURE_MSG + "test_id" , argumentCaptor .getValue ().getMessage ());
200285 }
286+
287+ public GetResponse prepareMLModel (MLModelState mlModelState ) throws IOException {
288+ MLModel mlModel = MLModel .builder ().modelId ("test_id" ).modelState (mlModelState ).build ();
289+ XContentBuilder content = mlModel .toXContent (XContentFactory .jsonBuilder (), ToXContent .EMPTY_PARAMS );
290+ BytesReference bytesReference = BytesReference .bytes (content );
291+ GetResult getResult = new GetResult ("indexName" , "111" , 111l , 111l , 111l , true , bytesReference , null , null );
292+ GetResponse getResponse = new GetResponse (getResult );
293+ return getResponse ;
294+ }
201295}
0 commit comments