1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.cloud.gaming.v1beta; 18 19 import static com.google.cloud.gaming.v1beta.RealmsServiceClient.ListRealmsPagedResponse; 20 21 import com.google.api.gax.core.NoCredentialsProvider; 22 import com.google.api.gax.httpjson.GaxHttpJsonProperties; 23 import com.google.api.gax.httpjson.testing.MockHttpService; 24 import com.google.api.gax.rpc.ApiClientHeaderProvider; 25 import com.google.api.gax.rpc.ApiException; 26 import com.google.api.gax.rpc.ApiExceptionFactory; 27 import com.google.api.gax.rpc.InvalidArgumentException; 28 import com.google.api.gax.rpc.StatusCode; 29 import com.google.api.gax.rpc.testing.FakeStatusCode; 30 import com.google.cloud.gaming.v1beta.stub.HttpJsonRealmsServiceStub; 31 import com.google.common.collect.Lists; 32 import com.google.longrunning.Operation; 33 import com.google.protobuf.Any; 34 import com.google.protobuf.Empty; 35 import com.google.protobuf.FieldMask; 36 import com.google.protobuf.Timestamp; 37 import java.io.IOException; 38 import java.util.Arrays; 39 import java.util.HashMap; 40 import java.util.List; 41 import java.util.concurrent.ExecutionException; 42 import javax.annotation.Generated; 43 import org.junit.After; 44 import org.junit.AfterClass; 45 import org.junit.Assert; 46 import org.junit.Before; 47 import org.junit.BeforeClass; 48 import org.junit.Test; 49 50 @Generated("by gapic-generator-java") 51 public class RealmsServiceClientHttpJsonTest { 52 private static MockHttpService mockService; 53 private static RealmsServiceClient client; 54 55 @BeforeClass startStaticServer()56 public static void startStaticServer() throws IOException { 57 mockService = 58 new MockHttpService( 59 HttpJsonRealmsServiceStub.getMethodDescriptors(), 60 RealmsServiceSettings.getDefaultEndpoint()); 61 RealmsServiceSettings settings = 62 RealmsServiceSettings.newHttpJsonBuilder() 63 .setTransportChannelProvider( 64 RealmsServiceSettings.defaultHttpJsonTransportProviderBuilder() 65 .setHttpTransport(mockService) 66 .build()) 67 .setCredentialsProvider(NoCredentialsProvider.create()) 68 .build(); 69 client = RealmsServiceClient.create(settings); 70 } 71 72 @AfterClass stopServer()73 public static void stopServer() { 74 client.close(); 75 } 76 77 @Before setUp()78 public void setUp() {} 79 80 @After tearDown()81 public void tearDown() throws Exception { 82 mockService.reset(); 83 } 84 85 @Test listRealmsTest()86 public void listRealmsTest() throws Exception { 87 Realm responsesElement = Realm.newBuilder().build(); 88 ListRealmsResponse expectedResponse = 89 ListRealmsResponse.newBuilder() 90 .setNextPageToken("") 91 .addAllRealms(Arrays.asList(responsesElement)) 92 .build(); 93 mockService.addResponse(expectedResponse); 94 95 LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]"); 96 97 ListRealmsPagedResponse pagedListResponse = client.listRealms(parent); 98 99 List<Realm> resources = Lists.newArrayList(pagedListResponse.iterateAll()); 100 101 Assert.assertEquals(1, resources.size()); 102 Assert.assertEquals(expectedResponse.getRealmsList().get(0), resources.get(0)); 103 104 List<String> actualRequests = mockService.getRequestPaths(); 105 Assert.assertEquals(1, actualRequests.size()); 106 107 String apiClientHeaderKey = 108 mockService 109 .getRequestHeaders() 110 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 111 .iterator() 112 .next(); 113 Assert.assertTrue( 114 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 115 .matcher(apiClientHeaderKey) 116 .matches()); 117 } 118 119 @Test listRealmsExceptionTest()120 public void listRealmsExceptionTest() throws Exception { 121 ApiException exception = 122 ApiExceptionFactory.createException( 123 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 124 mockService.addException(exception); 125 126 try { 127 LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]"); 128 client.listRealms(parent); 129 Assert.fail("No exception raised"); 130 } catch (InvalidArgumentException e) { 131 // Expected exception. 132 } 133 } 134 135 @Test listRealmsTest2()136 public void listRealmsTest2() throws Exception { 137 Realm responsesElement = Realm.newBuilder().build(); 138 ListRealmsResponse expectedResponse = 139 ListRealmsResponse.newBuilder() 140 .setNextPageToken("") 141 .addAllRealms(Arrays.asList(responsesElement)) 142 .build(); 143 mockService.addResponse(expectedResponse); 144 145 String parent = "projects/project-5833/locations/location-5833"; 146 147 ListRealmsPagedResponse pagedListResponse = client.listRealms(parent); 148 149 List<Realm> resources = Lists.newArrayList(pagedListResponse.iterateAll()); 150 151 Assert.assertEquals(1, resources.size()); 152 Assert.assertEquals(expectedResponse.getRealmsList().get(0), resources.get(0)); 153 154 List<String> actualRequests = mockService.getRequestPaths(); 155 Assert.assertEquals(1, actualRequests.size()); 156 157 String apiClientHeaderKey = 158 mockService 159 .getRequestHeaders() 160 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 161 .iterator() 162 .next(); 163 Assert.assertTrue( 164 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 165 .matcher(apiClientHeaderKey) 166 .matches()); 167 } 168 169 @Test listRealmsExceptionTest2()170 public void listRealmsExceptionTest2() throws Exception { 171 ApiException exception = 172 ApiExceptionFactory.createException( 173 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 174 mockService.addException(exception); 175 176 try { 177 String parent = "projects/project-5833/locations/location-5833"; 178 client.listRealms(parent); 179 Assert.fail("No exception raised"); 180 } catch (InvalidArgumentException e) { 181 // Expected exception. 182 } 183 } 184 185 @Test getRealmTest()186 public void getRealmTest() throws Exception { 187 Realm expectedResponse = 188 Realm.newBuilder() 189 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 190 .setCreateTime(Timestamp.newBuilder().build()) 191 .setUpdateTime(Timestamp.newBuilder().build()) 192 .putAllLabels(new HashMap<String, String>()) 193 .setTimeZone("timeZone-2077180903") 194 .setEtag("etag3123477") 195 .setDescription("description-1724546052") 196 .build(); 197 mockService.addResponse(expectedResponse); 198 199 RealmName name = RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]"); 200 201 Realm actualResponse = client.getRealm(name); 202 Assert.assertEquals(expectedResponse, actualResponse); 203 204 List<String> actualRequests = mockService.getRequestPaths(); 205 Assert.assertEquals(1, actualRequests.size()); 206 207 String apiClientHeaderKey = 208 mockService 209 .getRequestHeaders() 210 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 211 .iterator() 212 .next(); 213 Assert.assertTrue( 214 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 215 .matcher(apiClientHeaderKey) 216 .matches()); 217 } 218 219 @Test getRealmExceptionTest()220 public void getRealmExceptionTest() throws Exception { 221 ApiException exception = 222 ApiExceptionFactory.createException( 223 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 224 mockService.addException(exception); 225 226 try { 227 RealmName name = RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]"); 228 client.getRealm(name); 229 Assert.fail("No exception raised"); 230 } catch (InvalidArgumentException e) { 231 // Expected exception. 232 } 233 } 234 235 @Test getRealmTest2()236 public void getRealmTest2() throws Exception { 237 Realm expectedResponse = 238 Realm.newBuilder() 239 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 240 .setCreateTime(Timestamp.newBuilder().build()) 241 .setUpdateTime(Timestamp.newBuilder().build()) 242 .putAllLabels(new HashMap<String, String>()) 243 .setTimeZone("timeZone-2077180903") 244 .setEtag("etag3123477") 245 .setDescription("description-1724546052") 246 .build(); 247 mockService.addResponse(expectedResponse); 248 249 String name = "projects/project-9444/locations/location-9444/realms/realm-9444"; 250 251 Realm actualResponse = client.getRealm(name); 252 Assert.assertEquals(expectedResponse, actualResponse); 253 254 List<String> actualRequests = mockService.getRequestPaths(); 255 Assert.assertEquals(1, actualRequests.size()); 256 257 String apiClientHeaderKey = 258 mockService 259 .getRequestHeaders() 260 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 261 .iterator() 262 .next(); 263 Assert.assertTrue( 264 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 265 .matcher(apiClientHeaderKey) 266 .matches()); 267 } 268 269 @Test getRealmExceptionTest2()270 public void getRealmExceptionTest2() throws Exception { 271 ApiException exception = 272 ApiExceptionFactory.createException( 273 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 274 mockService.addException(exception); 275 276 try { 277 String name = "projects/project-9444/locations/location-9444/realms/realm-9444"; 278 client.getRealm(name); 279 Assert.fail("No exception raised"); 280 } catch (InvalidArgumentException e) { 281 // Expected exception. 282 } 283 } 284 285 @Test createRealmTest()286 public void createRealmTest() throws Exception { 287 Realm expectedResponse = 288 Realm.newBuilder() 289 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 290 .setCreateTime(Timestamp.newBuilder().build()) 291 .setUpdateTime(Timestamp.newBuilder().build()) 292 .putAllLabels(new HashMap<String, String>()) 293 .setTimeZone("timeZone-2077180903") 294 .setEtag("etag3123477") 295 .setDescription("description-1724546052") 296 .build(); 297 Operation resultOperation = 298 Operation.newBuilder() 299 .setName("createRealmTest") 300 .setDone(true) 301 .setResponse(Any.pack(expectedResponse)) 302 .build(); 303 mockService.addResponse(resultOperation); 304 305 LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]"); 306 Realm realm = Realm.newBuilder().build(); 307 String realmId = "realmId1080654858"; 308 309 Realm actualResponse = client.createRealmAsync(parent, realm, realmId).get(); 310 Assert.assertEquals(expectedResponse, actualResponse); 311 312 List<String> actualRequests = mockService.getRequestPaths(); 313 Assert.assertEquals(1, actualRequests.size()); 314 315 String apiClientHeaderKey = 316 mockService 317 .getRequestHeaders() 318 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 319 .iterator() 320 .next(); 321 Assert.assertTrue( 322 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 323 .matcher(apiClientHeaderKey) 324 .matches()); 325 } 326 327 @Test createRealmExceptionTest()328 public void createRealmExceptionTest() throws Exception { 329 ApiException exception = 330 ApiExceptionFactory.createException( 331 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 332 mockService.addException(exception); 333 334 try { 335 LocationName parent = LocationName.of("[PROJECT]", "[LOCATION]"); 336 Realm realm = Realm.newBuilder().build(); 337 String realmId = "realmId1080654858"; 338 client.createRealmAsync(parent, realm, realmId).get(); 339 Assert.fail("No exception raised"); 340 } catch (ExecutionException e) { 341 } 342 } 343 344 @Test createRealmTest2()345 public void createRealmTest2() throws Exception { 346 Realm expectedResponse = 347 Realm.newBuilder() 348 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 349 .setCreateTime(Timestamp.newBuilder().build()) 350 .setUpdateTime(Timestamp.newBuilder().build()) 351 .putAllLabels(new HashMap<String, String>()) 352 .setTimeZone("timeZone-2077180903") 353 .setEtag("etag3123477") 354 .setDescription("description-1724546052") 355 .build(); 356 Operation resultOperation = 357 Operation.newBuilder() 358 .setName("createRealmTest") 359 .setDone(true) 360 .setResponse(Any.pack(expectedResponse)) 361 .build(); 362 mockService.addResponse(resultOperation); 363 364 String parent = "projects/project-5833/locations/location-5833"; 365 Realm realm = Realm.newBuilder().build(); 366 String realmId = "realmId1080654858"; 367 368 Realm actualResponse = client.createRealmAsync(parent, realm, realmId).get(); 369 Assert.assertEquals(expectedResponse, actualResponse); 370 371 List<String> actualRequests = mockService.getRequestPaths(); 372 Assert.assertEquals(1, actualRequests.size()); 373 374 String apiClientHeaderKey = 375 mockService 376 .getRequestHeaders() 377 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 378 .iterator() 379 .next(); 380 Assert.assertTrue( 381 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 382 .matcher(apiClientHeaderKey) 383 .matches()); 384 } 385 386 @Test createRealmExceptionTest2()387 public void createRealmExceptionTest2() throws Exception { 388 ApiException exception = 389 ApiExceptionFactory.createException( 390 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 391 mockService.addException(exception); 392 393 try { 394 String parent = "projects/project-5833/locations/location-5833"; 395 Realm realm = Realm.newBuilder().build(); 396 String realmId = "realmId1080654858"; 397 client.createRealmAsync(parent, realm, realmId).get(); 398 Assert.fail("No exception raised"); 399 } catch (ExecutionException e) { 400 } 401 } 402 403 @Test deleteRealmTest()404 public void deleteRealmTest() throws Exception { 405 Empty expectedResponse = Empty.newBuilder().build(); 406 Operation resultOperation = 407 Operation.newBuilder() 408 .setName("deleteRealmTest") 409 .setDone(true) 410 .setResponse(Any.pack(expectedResponse)) 411 .build(); 412 mockService.addResponse(resultOperation); 413 414 RealmName name = RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]"); 415 416 client.deleteRealmAsync(name).get(); 417 418 List<String> actualRequests = mockService.getRequestPaths(); 419 Assert.assertEquals(1, actualRequests.size()); 420 421 String apiClientHeaderKey = 422 mockService 423 .getRequestHeaders() 424 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 425 .iterator() 426 .next(); 427 Assert.assertTrue( 428 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 429 .matcher(apiClientHeaderKey) 430 .matches()); 431 } 432 433 @Test deleteRealmExceptionTest()434 public void deleteRealmExceptionTest() throws Exception { 435 ApiException exception = 436 ApiExceptionFactory.createException( 437 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 438 mockService.addException(exception); 439 440 try { 441 RealmName name = RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]"); 442 client.deleteRealmAsync(name).get(); 443 Assert.fail("No exception raised"); 444 } catch (ExecutionException e) { 445 } 446 } 447 448 @Test deleteRealmTest2()449 public void deleteRealmTest2() throws Exception { 450 Empty expectedResponse = Empty.newBuilder().build(); 451 Operation resultOperation = 452 Operation.newBuilder() 453 .setName("deleteRealmTest") 454 .setDone(true) 455 .setResponse(Any.pack(expectedResponse)) 456 .build(); 457 mockService.addResponse(resultOperation); 458 459 String name = "projects/project-9444/locations/location-9444/realms/realm-9444"; 460 461 client.deleteRealmAsync(name).get(); 462 463 List<String> actualRequests = mockService.getRequestPaths(); 464 Assert.assertEquals(1, actualRequests.size()); 465 466 String apiClientHeaderKey = 467 mockService 468 .getRequestHeaders() 469 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 470 .iterator() 471 .next(); 472 Assert.assertTrue( 473 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 474 .matcher(apiClientHeaderKey) 475 .matches()); 476 } 477 478 @Test deleteRealmExceptionTest2()479 public void deleteRealmExceptionTest2() throws Exception { 480 ApiException exception = 481 ApiExceptionFactory.createException( 482 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 483 mockService.addException(exception); 484 485 try { 486 String name = "projects/project-9444/locations/location-9444/realms/realm-9444"; 487 client.deleteRealmAsync(name).get(); 488 Assert.fail("No exception raised"); 489 } catch (ExecutionException e) { 490 } 491 } 492 493 @Test updateRealmTest()494 public void updateRealmTest() throws Exception { 495 Realm expectedResponse = 496 Realm.newBuilder() 497 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 498 .setCreateTime(Timestamp.newBuilder().build()) 499 .setUpdateTime(Timestamp.newBuilder().build()) 500 .putAllLabels(new HashMap<String, String>()) 501 .setTimeZone("timeZone-2077180903") 502 .setEtag("etag3123477") 503 .setDescription("description-1724546052") 504 .build(); 505 Operation resultOperation = 506 Operation.newBuilder() 507 .setName("updateRealmTest") 508 .setDone(true) 509 .setResponse(Any.pack(expectedResponse)) 510 .build(); 511 mockService.addResponse(resultOperation); 512 513 Realm realm = 514 Realm.newBuilder() 515 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 516 .setCreateTime(Timestamp.newBuilder().build()) 517 .setUpdateTime(Timestamp.newBuilder().build()) 518 .putAllLabels(new HashMap<String, String>()) 519 .setTimeZone("timeZone-2077180903") 520 .setEtag("etag3123477") 521 .setDescription("description-1724546052") 522 .build(); 523 FieldMask updateMask = FieldMask.newBuilder().build(); 524 525 Realm actualResponse = client.updateRealmAsync(realm, updateMask).get(); 526 Assert.assertEquals(expectedResponse, actualResponse); 527 528 List<String> actualRequests = mockService.getRequestPaths(); 529 Assert.assertEquals(1, actualRequests.size()); 530 531 String apiClientHeaderKey = 532 mockService 533 .getRequestHeaders() 534 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 535 .iterator() 536 .next(); 537 Assert.assertTrue( 538 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 539 .matcher(apiClientHeaderKey) 540 .matches()); 541 } 542 543 @Test updateRealmExceptionTest()544 public void updateRealmExceptionTest() throws Exception { 545 ApiException exception = 546 ApiExceptionFactory.createException( 547 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 548 mockService.addException(exception); 549 550 try { 551 Realm realm = 552 Realm.newBuilder() 553 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 554 .setCreateTime(Timestamp.newBuilder().build()) 555 .setUpdateTime(Timestamp.newBuilder().build()) 556 .putAllLabels(new HashMap<String, String>()) 557 .setTimeZone("timeZone-2077180903") 558 .setEtag("etag3123477") 559 .setDescription("description-1724546052") 560 .build(); 561 FieldMask updateMask = FieldMask.newBuilder().build(); 562 client.updateRealmAsync(realm, updateMask).get(); 563 Assert.fail("No exception raised"); 564 } catch (ExecutionException e) { 565 } 566 } 567 568 @Test previewRealmUpdateTest()569 public void previewRealmUpdateTest() throws Exception { 570 PreviewRealmUpdateResponse expectedResponse = 571 PreviewRealmUpdateResponse.newBuilder() 572 .setEtag("etag3123477") 573 .setTargetState(TargetState.newBuilder().build()) 574 .build(); 575 mockService.addResponse(expectedResponse); 576 577 PreviewRealmUpdateRequest request = 578 PreviewRealmUpdateRequest.newBuilder() 579 .setRealm( 580 Realm.newBuilder() 581 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 582 .setCreateTime(Timestamp.newBuilder().build()) 583 .setUpdateTime(Timestamp.newBuilder().build()) 584 .putAllLabels(new HashMap<String, String>()) 585 .setTimeZone("timeZone-2077180903") 586 .setEtag("etag3123477") 587 .setDescription("description-1724546052") 588 .build()) 589 .setUpdateMask(FieldMask.newBuilder().build()) 590 .setPreviewTime(Timestamp.newBuilder().build()) 591 .build(); 592 593 PreviewRealmUpdateResponse actualResponse = client.previewRealmUpdate(request); 594 Assert.assertEquals(expectedResponse, actualResponse); 595 596 List<String> actualRequests = mockService.getRequestPaths(); 597 Assert.assertEquals(1, actualRequests.size()); 598 599 String apiClientHeaderKey = 600 mockService 601 .getRequestHeaders() 602 .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey()) 603 .iterator() 604 .next(); 605 Assert.assertTrue( 606 GaxHttpJsonProperties.getDefaultApiClientHeaderPattern() 607 .matcher(apiClientHeaderKey) 608 .matches()); 609 } 610 611 @Test previewRealmUpdateExceptionTest()612 public void previewRealmUpdateExceptionTest() throws Exception { 613 ApiException exception = 614 ApiExceptionFactory.createException( 615 new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false); 616 mockService.addException(exception); 617 618 try { 619 PreviewRealmUpdateRequest request = 620 PreviewRealmUpdateRequest.newBuilder() 621 .setRealm( 622 Realm.newBuilder() 623 .setName(RealmName.of("[PROJECT]", "[LOCATION]", "[REALM]").toString()) 624 .setCreateTime(Timestamp.newBuilder().build()) 625 .setUpdateTime(Timestamp.newBuilder().build()) 626 .putAllLabels(new HashMap<String, String>()) 627 .setTimeZone("timeZone-2077180903") 628 .setEtag("etag3123477") 629 .setDescription("description-1724546052") 630 .build()) 631 .setUpdateMask(FieldMask.newBuilder().build()) 632 .setPreviewTime(Timestamp.newBuilder().build()) 633 .build(); 634 client.previewRealmUpdate(request); 635 Assert.fail("No exception raised"); 636 } catch (InvalidArgumentException e) { 637 // Expected exception. 638 } 639 } 640 } 641