55import static com .github .tomakehurst .wiremock .client .WireMock .get ;
66import static com .github .tomakehurst .wiremock .client .WireMock .getRequestedFor ;
77import static com .github .tomakehurst .wiremock .client .WireMock .urlPathEqualTo ;
8+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
89
910import com .sap .ai .sdk .core .client .WireMockTestServer ;
10- import org .apache .hc .core5 .http .HttpStatus ;
11+ import com .sap .cloud .sdk .cloudplatform .connectivity .DefaultHttpDestination ;
12+ import java .util .NoSuchElementException ;
1113import org .junit .jupiter .api .BeforeEach ;
1214import org .junit .jupiter .api .Test ;
1315
@@ -20,67 +22,24 @@ void setupCache() {
2022 wireMockServer .resetRequests ();
2123 }
2224
23- private static void stubGPT4 () {
25+ private static void stubGPT4 (String resourceGroup ) {
2426 wireMockServer .stubFor (
2527 get (urlPathEqualTo ("/v2/lm/deployments" ))
26- .withHeader ("AI-Resource-Group" , equalTo ("default" ))
28+ .withHeader ("AI-Resource-Group" , equalTo (resourceGroup ))
2729 .willReturn (
2830 aResponse ()
29- .withStatus (HttpStatus .SC_OK )
30- .withHeader ("content-type" , "application/json" )
31- .withBody (
32- """
33- {
34- "count": 1,
35- "resources": [
36- {
37- "configurationId": "7652a231-ba9b-4fcc-b473-2c355cb21b61",
38- "configurationName": "gpt-4-32k",
39- "createdAt": "2024-04-17T15:19:53Z",
40- "deploymentUrl": "https://api.ai.intprod-eu12.eu-central-1.aws.ml.hana.ondemand.com/v2/inference/deployments/d19b998f347341aa",
41- "details": {
42- "resources": {
43- "backend_details": {
44- "model": {
45- "name": "gpt-4-32k",
46- "version": "latest"
47- }
48- }
49- },
50- "scaling": {
51- "backend_details": {}
52- }
53- },
54- "id": "d19b998f347341aa",
55- "lastOperation": "CREATE",
56- "latestRunningConfigurationId": "7652a231-ba9b-4fcc-b473-2c355cb21b61",
57- "modifiedAt": "2024-05-07T13:05:45Z",
58- "scenarioId": "foundation-models",
59- "startTime": "2024-04-17T15:21:15Z",
60- "status": "RUNNING",
61- "submissionTime": "2024-04-17T15:20:11Z",
62- "targetStatus": "RUNNING"
63- }
64- ]
65- }
66- """ )));
31+ .withBodyFile ("GPT4DeploymentResponse.json" )
32+ .withHeader ("Content-Type" , "application/json" )));
6733 }
6834
69- private static void stubEmpty () {
35+ private static void stubEmpty (String resourceGroup ) {
7036 wireMockServer .stubFor (
7137 get (urlPathEqualTo ("/v2/lm/deployments" ))
72- .withHeader ("AI-Resource-Group" , equalTo ("default" ))
38+ .withHeader ("AI-Resource-Group" , equalTo (resourceGroup ))
7339 .willReturn (
7440 aResponse ()
75- .withStatus (HttpStatus .SC_OK )
76- .withHeader ("content-type" , "application/json" )
77- .withBody (
78- """
79- {
80- "count": 0,
81- "resources": []
82- }
83- """ )));
41+ .withBodyFile ("emptyDeploymentResponse.json" )
42+ .withHeader ("content-type" , "application/json" )));
8443 }
8544
8645 /**
@@ -94,31 +53,16 @@ private static void stubEmpty() {
9453 */
9554 @ Test
9655 void newDeployment () {
97- stubGPT4 () ;
98- cacheUnderTest . loadCache ( client , "default" );
56+ String resourceGroup = "default" ;
57+ stubGPT4 ( resourceGroup );
9958
100- cacheUnderTest .getDeploymentIdByModel (client , "default" , "gpt-4-32k" );
59+ cacheUnderTest .getDeploymentIdByModel (client , resourceGroup , "gpt-4-32k" );
10160 wireMockServer .verify (1 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
10261
103- cacheUnderTest .getDeploymentIdByModel (client , "default" , "gpt-4-32k" );
62+ cacheUnderTest .getDeploymentIdByModel (client , resourceGroup , "gpt-4-32k" );
10463 wireMockServer .verify (1 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
10564 }
10665
107- @ Test
108- void clearCache () {
109- stubGPT4 ();
110- cacheUnderTest .loadCache (client , "default" );
111-
112- cacheUnderTest .getDeploymentIdByModel (client , "default" , "gpt-4-32k" );
113- wireMockServer .verify (1 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
114-
115- cacheUnderTest .clearCache ();
116-
117- cacheUnderTest .getDeploymentIdByModel (client , "default" , "gpt-4-32k" );
118- // the deployment is not in the cache anymore, so we need to query it again
119- wireMockServer .verify (2 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
120- }
121-
12266 /**
12367 * The user creates a deployment after starting with an empty cache.
12468 *
@@ -130,15 +74,57 @@ void clearCache() {
13074 */
13175 @ Test
13276 void newDeploymentAfterReset () {
133- stubEmpty ();
134- cacheUnderTest .loadCache (client , "default" );
135- stubGPT4 ();
77+ String resourceGroup = "default" ;
78+ stubEmpty (resourceGroup );
79+ cacheUnderTest .resetCache (client , resourceGroup );
80+ stubGPT4 (resourceGroup );
13681
137- cacheUnderTest .getDeploymentIdByModel (client , "default" , "gpt-4-32k" );
82+ cacheUnderTest .getDeploymentIdByModel (client , resourceGroup , "gpt-4-32k" );
13883 // 1 reset empty and 1 cache miss
13984 wireMockServer .verify (2 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
14085
141- cacheUnderTest .getDeploymentIdByModel (client , "default" , "gpt-4-32k" );
86+ cacheUnderTest .getDeploymentIdByModel (client , resourceGroup , "gpt-4-32k" );
87+ wireMockServer .verify (2 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
88+ }
89+
90+ @ Test
91+ void resourceGroupIsolation () {
92+ String resourceGroupA = "A" ;
93+ String resourceGroupB = "B" ;
94+ stubGPT4 (resourceGroupA );
95+ stubGPT4 (resourceGroupB );
96+
97+ cacheUnderTest .getDeploymentIdByModel (client , resourceGroupA , "gpt-4-32k" );
98+ wireMockServer .verify (
99+ 1 ,
100+ getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" ))
101+ .withHeader ("AI-Resource-Group" , equalTo (resourceGroupA )));
102+ wireMockServer .verify (
103+ 0 ,
104+ getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" ))
105+ .withHeader ("AI-Resource-Group" , equalTo (resourceGroupB )));
106+ }
107+
108+ @ Test
109+ void exceptionDeploymentNotFound () {
110+ String resourceGroup = "default" ;
111+ stubEmpty (resourceGroup );
112+
113+ assertThatThrownBy (
114+ () -> cacheUnderTest .getDeploymentIdByModel (client , resourceGroup , "gpt-4-32k" ))
115+ .isExactlyInstanceOf (NoSuchElementException .class )
116+ .hasMessageContaining ("No running deployment found for model: gpt-4-32k" );
117+ }
118+
119+ @ Test
120+ void resetCache () {
121+ String resourceGroup = "default" ;
122+ stubGPT4 (resourceGroup );
123+ cacheUnderTest .resetCache (client , resourceGroup );
124+ wireMockServer .verify (1 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
125+
126+ final var destination = DefaultHttpDestination .builder (wireMockServer .baseUrl ()).build ();
127+ new AiCoreService ().withDestination (destination ).reloadCachedDeployments (resourceGroup );
142128 wireMockServer .verify (2 , getRequestedFor (urlPathEqualTo ("/v2/lm/deployments" )));
143129 }
144130}
0 commit comments