|
16 | 16 | import static org.easymock.EasyMock.createMock; |
17 | 17 | import static org.easymock.EasyMock.expect; |
18 | 18 | import static org.easymock.EasyMock.replay; |
| 19 | +import static org.hamcrest.CoreMatchers.instanceOf; |
19 | 20 | import static org.hamcrest.MatcherAssert.assertThat; |
20 | 21 | import static org.hamcrest.Matchers.containsInAnyOrder; |
21 | 22 | import static org.hamcrest.Matchers.greaterThan; |
|
31 | 32 | import static org.junit.Assert.assertThrows; |
32 | 33 | import static org.junit.Assert.assertTrue; |
33 | 34 | import static org.junit.Assert.fail; |
| 35 | +import static org.mockito.Mockito.doThrow; |
34 | 36 | import static org.mockito.Mockito.mock; |
35 | 37 | import static org.mockito.Mockito.when; |
36 | 38 |
|
37 | 39 | import java.io.File; |
38 | 40 | import java.io.FileInputStream; |
| 41 | +import java.io.FilterOutputStream; |
39 | 42 | import java.io.IOException; |
| 43 | +import java.io.OutputStream; |
40 | 44 | import java.net.URL; |
41 | 45 | import java.util.ArrayList; |
42 | 46 | import java.util.Arrays; |
|
67 | 71 | import org.geowebcache.grid.SRS; |
68 | 72 | import org.geowebcache.layer.TileLayer; |
69 | 73 | import org.geowebcache.layer.wms.WMSLayer; |
| 74 | +import org.geowebcache.storage.UnsuitableStorageException; |
70 | 75 | import org.geowebcache.util.TestUtils; |
71 | 76 | import org.junit.Assume; |
72 | 77 | import org.junit.Before; |
73 | 78 | import org.junit.Rule; |
74 | 79 | import org.junit.Test; |
75 | 80 | import org.junit.rules.TemporaryFolder; |
| 81 | +import org.mockito.Mockito; |
76 | 82 | import org.springframework.context.ApplicationContext; |
| 83 | +import org.springframework.web.context.WebApplicationContext; |
77 | 84 | import org.xml.sax.SAXParseException; |
78 | 85 |
|
79 | 86 | public class XMLConfigurationTest { |
@@ -477,7 +484,7 @@ public void testNoBlobStores() throws Exception { |
477 | 484 | } |
478 | 485 |
|
479 | 486 | @Test |
480 | | - public void testSaveBlobStores() throws Exception { |
| 487 | + public void testAddBlobStores() throws Exception { |
481 | 488 | FileBlobStoreInfo store1 = new FileBlobStoreInfo(); |
482 | 489 | store1.setName("store1"); |
483 | 490 | store1.setDefault(true); |
@@ -517,6 +524,150 @@ public void testSaveBlobStores() throws Exception { |
517 | 524 | assertEquals(store2, stores.get(1)); |
518 | 525 | } |
519 | 526 |
|
| 527 | + @Test |
| 528 | + public void testAddBlobStoreExceptionSaving() throws Exception { |
| 529 | + |
| 530 | + XMLFileResourceProvider resourceProvider = |
| 531 | + new XMLFileResourceProvider( |
| 532 | + XMLConfiguration.DEFAULT_CONFIGURATION_FILE_NAME, |
| 533 | + (WebApplicationContext) null, |
| 534 | + this.configDir.getAbsolutePath(), |
| 535 | + null) { |
| 536 | + |
| 537 | + // throw an ioexception the first time close() is called, the second time is the roll-back |
| 538 | + private boolean thrown = false; |
| 539 | + |
| 540 | + @Override |
| 541 | + public OutputStream out() throws IOException { |
| 542 | + OutputStream real = super.out(); |
| 543 | + return new FilterOutputStream(real) { |
| 544 | + |
| 545 | + @Override |
| 546 | + public void close() throws IOException { |
| 547 | + real.close(); |
| 548 | + if (thrown) { |
| 549 | + return; |
| 550 | + } |
| 551 | + thrown = true; |
| 552 | + throw new IOException("forced io exception"); |
| 553 | + } |
| 554 | + }; |
| 555 | + } |
| 556 | + }; |
| 557 | + |
| 558 | + config = new XMLConfiguration(null, resourceProvider); |
| 559 | + config.setGridSetBroker(gridSetBroker); |
| 560 | + |
| 561 | + FileBlobStoreInfo store1 = new FileBlobStoreInfo(); |
| 562 | + store1.setName("store1"); |
| 563 | + store1.setDefault(true); |
| 564 | + store1.setEnabled(true); |
| 565 | + store1.setFileSystemBlockSize(8096); |
| 566 | + store1.setBaseDirectory("/tmp/test"); |
| 567 | + |
| 568 | + assertThrows(ConfigurationPersistenceException.class, () -> config.addBlobStore(store1)); |
| 569 | + assertEquals(0, config.getBlobStoreCount()); |
| 570 | + GeoWebCacheConfiguration configuration = config.loadConfiguration(); |
| 571 | + assertTrue("store shouldn't be saved", configuration.getBlobStores().isEmpty()); |
| 572 | + } |
| 573 | + |
| 574 | + /** |
| 575 | + * Verifies the blobstore configuration is rolled back from the persisted configuration if a |
| 576 | + * {@link BlobStoreConfigurationListener#handleAddBlobStore} throws an {@link UnsuitableStorageException}. |
| 577 | + * |
| 578 | + * <p>Note I'm not sure why XMLConfiguration.addBlobStore() only rolls-back on UnsuitableStorageException and not on |
| 579 | + * IOException or GeoWebCacheException |
| 580 | + */ |
| 581 | + @Test |
| 582 | + public void testAddBlobStoreExceptionFromListener() throws Exception { |
| 583 | + FileBlobStoreInfo store1 = new FileBlobStoreInfo(); |
| 584 | + store1.setName("store1"); |
| 585 | + store1.setDefault(true); |
| 586 | + store1.setEnabled(true); |
| 587 | + store1.setFileSystemBlockSize(8096); |
| 588 | + store1.setBaseDirectory("/tmp/test"); |
| 589 | + |
| 590 | + BlobStoreConfigurationListener listener; |
| 591 | + |
| 592 | + listener = mock(BlobStoreConfigurationListener.class); |
| 593 | + doThrow(new UnsuitableStorageException("fake")).when(listener).handleAddBlobStore(Mockito.any()); |
| 594 | + config.addBlobStoreListener(listener); |
| 595 | + |
| 596 | + assertAddBlobStoreFails(store1, UnsuitableStorageException.class); |
| 597 | + |
| 598 | + // note, I'm not sure why XMLConfiguration.addBlobStore() only rolls-back on UnsuitableStorageException and not |
| 599 | + // on IOException or GeoWebCacheException |
| 600 | + // doThrow(new IOException("fake")).when(listener).handleAddBlobStore(Mockito.any()); |
| 601 | + // assertAddBlobStoreFails(store1, IOException.class); |
| 602 | + // |
| 603 | + // doThrow(new GeoWebCacheException("fake")).when(listener).handleAddBlobStore(Mockito.any()); |
| 604 | + // assertAddBlobStoreFails(store1, GeoWebCacheException.class); |
| 605 | + } |
| 606 | + |
| 607 | + private void assertAddBlobStoreFails(FileBlobStoreInfo store, Class<? extends Exception> expectedCause) |
| 608 | + throws ConfigurationException { |
| 609 | + ConfigurationPersistenceException expected; |
| 610 | + expected = assertThrows(ConfigurationPersistenceException.class, () -> config.addBlobStore(store)); |
| 611 | + assertThat(expected.getCause(), instanceOf(expectedCause)); |
| 612 | + assertEquals(0, config.getBlobStoreCount()); |
| 613 | + GeoWebCacheConfiguration configuration = config.loadConfiguration(); |
| 614 | + assertTrue("store shouldn't be saved", configuration.getBlobStores().isEmpty()); |
| 615 | + } |
| 616 | + |
| 617 | + /** |
| 618 | + * Verifies the blobstore configuration is rolled back from the persisted configuration if a |
| 619 | + * {@link BlobStoreConfigurationListener#handleModifyBlobStore(BlobStoreInfo)} throws an |
| 620 | + * {@link UnsuitableStorageException}. |
| 621 | + * |
| 622 | + * <p>Note I'm not sure why XMLConfiguration.modifyBobstore() only rolls-back on UnsuitableStorageException and not |
| 623 | + * on IOException or GeoWebCacheException |
| 624 | + */ |
| 625 | + @Test |
| 626 | + public void testModifyBlobStoreExceptionFromListener() throws Exception { |
| 627 | + FileBlobStoreInfo original = new FileBlobStoreInfo(); |
| 628 | + original.setName("store1"); |
| 629 | + original.setDefault(true); |
| 630 | + original.setEnabled(true); |
| 631 | + original.setFileSystemBlockSize(8096); |
| 632 | + original.setBaseDirectory("/tmp/test"); |
| 633 | + |
| 634 | + config.addBlobStore(original); |
| 635 | + |
| 636 | + BlobStoreConfigurationListener listener; |
| 637 | + |
| 638 | + listener = mock(BlobStoreConfigurationListener.class); |
| 639 | + doThrow(new UnsuitableStorageException("fake")).when(listener).handleModifyBlobStore(Mockito.any()); |
| 640 | + config.addBlobStoreListener(listener); |
| 641 | + |
| 642 | + assertModifyBlobStoreFails(original, UnsuitableStorageException.class); |
| 643 | + |
| 644 | + // note, I'm not sure why XMLConfiguration.addBlobStore() only rolls-back on UnsuitableStorageException and not |
| 645 | + // on IOException or GeoWebCacheException |
| 646 | + // doThrow(new IOException("fake")).when(listener).handleModifyBlobStore(Mockito.any()); |
| 647 | + // assertModifyBlobStoreFails(original, IOException.class); |
| 648 | + // |
| 649 | + // doThrow(new GeoWebCacheException("fake")).when(listener).handleModifyBlobStore(Mockito.any()); |
| 650 | + // assertModifyBlobStoreFails(original, GeoWebCacheException.class); |
| 651 | + } |
| 652 | + |
| 653 | + private void assertModifyBlobStoreFails(FileBlobStoreInfo original, Class<? extends Exception> expectedCause) |
| 654 | + throws ConfigurationException { |
| 655 | + |
| 656 | + FileBlobStoreInfo modified = (FileBlobStoreInfo) original.clone(); |
| 657 | + modified.setBaseDirectory("/tmp/test2"); |
| 658 | + |
| 659 | + assertEquals(1, config.getBlobStoreCount()); |
| 660 | + |
| 661 | + ConfigurationPersistenceException expected; |
| 662 | + expected = assertThrows(ConfigurationPersistenceException.class, () -> config.modifyBlobStore(modified)); |
| 663 | + assertThat(expected.getCause(), instanceOf(expectedCause)); |
| 664 | + GeoWebCacheConfiguration reloaded = config.loadConfiguration(); |
| 665 | + assertEquals(1, reloaded.getBlobStores().size()); |
| 666 | + |
| 667 | + BlobStoreInfo stored = reloaded.getBlobStores().get(0); |
| 668 | + assertEquals("store shouldn't be saved", original, stored); |
| 669 | + } |
| 670 | + |
520 | 671 | @Test |
521 | 672 | public void testSaveCurrentVersion() throws Exception { |
522 | 673 |
|
|
0 commit comments