/dbpool/src/test/java/io/airlift/dbpool/TestH2EmbeddedDataSourceModule.java

https://gitlab.com/CORP-RESELLER/airlift · Java · 258 lines · 184 code · 49 blank · 25 comment · 1 complexity · c03421e96a1a54c7c50d552497e8b1e2 MD5 · raw file

  1. /*
  2. * Copyright 2010 Proofpoint, Inc.
  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. * http://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. package io.airlift.dbpool;
  17. import com.google.common.collect.ImmutableList;
  18. import com.google.inject.Binder;
  19. import com.google.inject.BindingAnnotation;
  20. import com.google.inject.CreationException;
  21. import com.google.inject.Guice;
  22. import com.google.inject.Inject;
  23. import com.google.inject.Injector;
  24. import com.google.inject.Module;
  25. import io.airlift.configuration.ConfigurationFactory;
  26. import io.airlift.configuration.ConfigurationModule;
  27. import io.airlift.testing.Assertions;
  28. import org.testng.annotations.AfterMethod;
  29. import org.testng.annotations.BeforeMethod;
  30. import org.testng.annotations.Test;
  31. import javax.management.MBeanServer;
  32. import javax.sql.DataSource;
  33. import java.io.File;
  34. import java.io.IOException;
  35. import java.lang.annotation.Retention;
  36. import java.util.HashMap;
  37. import java.util.List;
  38. import java.util.Map;
  39. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  40. import static org.mockito.Mockito.mock;
  41. import static org.testng.Assert.assertEquals;
  42. import static org.testng.Assert.assertNotSame;
  43. import static org.testng.Assert.assertSame;
  44. public class TestH2EmbeddedDataSourceModule
  45. {
  46. @Retention(RUNTIME)
  47. @BindingAnnotation
  48. public @interface MainBinding
  49. {
  50. }
  51. @Retention(RUNTIME)
  52. @BindingAnnotation
  53. public @interface AliasBinding
  54. {
  55. }
  56. public static class ObjectHolder
  57. {
  58. public final DataSource dataSource;
  59. @Inject
  60. public ObjectHolder(@MainBinding DataSource dataSource)
  61. {
  62. this.dataSource = dataSource;
  63. }
  64. }
  65. public static class TwoObjectsHolder
  66. {
  67. public final DataSource mainDataSource;
  68. public final DataSource aliasedDataSource;
  69. @Inject
  70. public TwoObjectsHolder(@MainBinding DataSource mainDataSource, @AliasBinding DataSource aliasedDataSource)
  71. {
  72. this.mainDataSource = mainDataSource;
  73. this.aliasedDataSource = aliasedDataSource;
  74. }
  75. }
  76. @Test(expectedExceptions = NullPointerException.class)
  77. public void testNullPrefixInConstructionThrows()
  78. {
  79. H2EmbeddedDataSourceModule notActuallyConstructed = new H2EmbeddedDataSourceModule(null, MainBinding.class);
  80. }
  81. @Test(expectedExceptions = NullPointerException.class)
  82. public void testNullAnnotationInConstructionThrows()
  83. {
  84. H2EmbeddedDataSourceModule notActuallyConstructed = new H2EmbeddedDataSourceModule("test", null);
  85. }
  86. @Test(expectedExceptions = IllegalArgumentException.class)
  87. public void testEmptyPrefixStringInConstructionThrows()
  88. {
  89. H2EmbeddedDataSourceModule notActuallyConstructed = new H2EmbeddedDataSourceModule("", MainBinding.class);
  90. }
  91. @Test(groups = "requiresTempFile")
  92. public void testObjectBindingFromInjector()
  93. {
  94. final String prefix = "test";
  95. Map<String, String> properties = createDefaultConfigurationProperties(prefix, temporaryFile.getAbsolutePath());
  96. Injector injector = createInjector(properties, new H2EmbeddedDataSourceModule(prefix, MainBinding.class));
  97. ObjectHolder objectHolder = injector.getInstance(ObjectHolder.class);
  98. Assertions.assertInstanceOf(objectHolder.dataSource, H2EmbeddedDataSource.class);
  99. }
  100. @Test(groups = "requiresTempFile")
  101. public void testBoundObjectIsASingleton()
  102. {
  103. final String prefix = "test";
  104. Map<String, String> properties = createDefaultConfigurationProperties(prefix, temporaryFile.getAbsolutePath());
  105. Injector injector = createInjector(properties, new H2EmbeddedDataSourceModule(prefix, MainBinding.class));
  106. ObjectHolder objectHolder1 = injector.getInstance(ObjectHolder.class);
  107. ObjectHolder objectHolder2 = injector.getInstance(ObjectHolder.class);
  108. // Holding objects should be different
  109. assertNotSame(objectHolder1, objectHolder2, "Expected holding objects to be different");
  110. // But held data source objects should be the same
  111. assertSame(objectHolder1.dataSource, objectHolder2.dataSource);
  112. }
  113. @Test(groups = "requiresTempFile")
  114. public void testAliasedBindingBindsCorrectly()
  115. {
  116. final String prefix = "test";
  117. Map<String, String> properties = createDefaultConfigurationProperties(prefix, temporaryFile.getAbsolutePath());
  118. Injector injector = createInjector(properties,
  119. new H2EmbeddedDataSourceModule(prefix, MainBinding.class, AliasBinding.class),
  120. new Module()
  121. {
  122. @Override
  123. public void configure(Binder binder)
  124. {
  125. binder.bind(TwoObjectsHolder.class);
  126. }
  127. }
  128. );
  129. ObjectHolder objectHolder = injector.getInstance(ObjectHolder.class);
  130. TwoObjectsHolder twoObjectsHolder = injector.getInstance(TwoObjectsHolder.class);
  131. // Held data source objects should all be of the correct type
  132. Assertions.assertInstanceOf(twoObjectsHolder.mainDataSource, H2EmbeddedDataSource.class);
  133. Assertions.assertInstanceOf(twoObjectsHolder.aliasedDataSource, H2EmbeddedDataSource.class);
  134. // And should all be references to the same object
  135. assertSame(objectHolder.dataSource, twoObjectsHolder.mainDataSource);
  136. assertSame(objectHolder.dataSource, twoObjectsHolder.aliasedDataSource);
  137. }
  138. @Test(groups = "requiresTempFile")
  139. public void testCorrectConfigurationPrefix()
  140. {
  141. final String expectedPrefix = "expected";
  142. final String otherPrefix = "additional";
  143. final String propertySuffixToTest = ".db.connections.max";
  144. final int expectedValue = 1234;
  145. // Required properties for construction
  146. Map<String, String> properties = createDefaultConfigurationProperties(expectedPrefix, temporaryFile.getAbsolutePath());
  147. // Optional property added with two different prefixes, two different values
  148. properties.put(otherPrefix + propertySuffixToTest, Integer.toString(expectedValue + 5678));
  149. properties.put(expectedPrefix + propertySuffixToTest, Integer.toString(expectedValue));
  150. Injector injector = createInjector(properties, new H2EmbeddedDataSourceModule(expectedPrefix, MainBinding.class));
  151. ObjectHolder objectHolder = injector.getInstance(ObjectHolder.class);
  152. // Make sure we picked up the value with the expected prefix
  153. Assertions.assertInstanceOf(objectHolder.dataSource, H2EmbeddedDataSource.class);
  154. H2EmbeddedDataSource created = (H2EmbeddedDataSource) objectHolder.dataSource;
  155. assertEquals(created.getMaxConnections(), expectedValue, "Property value not loaded from correct prefix");
  156. }
  157. @Test(groups = "requiresTempFile", expectedExceptions = CreationException.class)
  158. public void testIncorrectConfigurationPrefixThrows()
  159. {
  160. final String configurationPrefix = "configuration";
  161. final String constructionPrefix = "differentFromConfiguration";
  162. Map<String, String> properties = createDefaultConfigurationProperties(configurationPrefix, temporaryFile.getAbsolutePath());
  163. // Will throw because construction will fail due to the incorrect prefixing.
  164. createInjector(properties, new H2EmbeddedDataSourceModule(constructionPrefix, MainBinding.class));
  165. }
  166. private static Injector createInjector(Map<String, String> properties, Module... modules)
  167. {
  168. ConfigurationFactory configurationFactory = new ConfigurationFactory(properties);
  169. // Required to bind a configuration module and an MBean server when binding an H2EmbeddedDataSourceModule
  170. List<Module> moduleList = ImmutableList.<Module>builder()
  171. .add(modules)
  172. .add(new ConfigurationModule(configurationFactory))
  173. .add(new Module() {
  174. @Override
  175. public void configure(Binder binder)
  176. {
  177. binder.bind(MBeanServer.class).toInstance(mock(MBeanServer.class));
  178. binder.bind(ObjectHolder.class);
  179. }
  180. })
  181. .build();
  182. return Guice.createInjector(moduleList);
  183. }
  184. // Any test that actually instantiates an H2EmbeddedDataSource requires a temporary file to use for the database
  185. private File temporaryFile;
  186. @BeforeMethod(groups = "requiresTempFile")
  187. private void createTempFile()
  188. throws IOException
  189. {
  190. this.temporaryFile = File.createTempFile("h2db-", ".db");
  191. }
  192. @AfterMethod(groups = "requiresTempFile")
  193. private void deleteTempFile()
  194. {
  195. this.temporaryFile.delete();
  196. }
  197. private static Map<String, String> createDefaultConfigurationProperties(String prefix, String filename)
  198. {
  199. Map<String, String> properties = new HashMap<String, String>();
  200. if (!prefix.endsWith(".")) {
  201. prefix = prefix + ".";
  202. }
  203. properties.put(prefix + "db.filename", filename);
  204. properties.put(prefix + "db.init-script", "io/airlift/dbpool/h2.ddl");
  205. properties.put(prefix + "db.cipher", "AES");
  206. properties.put(prefix + "db.file-password", "filePassword");
  207. return properties;
  208. }
  209. }