PageRenderTime 43ms CodeModel.GetById 18ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/configuration/src/test/java/io/airlift/configuration/ConfigurationFactoryTest.java

https://gitlab.com/github-cloud-corp/airlift
Java | 464 lines | 399 code | 49 blank | 16 comment | 0 complexity | d34b39dc457f375bf4c52a655b3e5463 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 */
 16package io.airlift.configuration;
 17
 18import com.google.common.collect.Maps;
 19import com.google.inject.Binder;
 20import com.google.inject.CreationException;
 21import com.google.inject.Guice;
 22import com.google.inject.Injector;
 23import com.google.inject.Module;
 24import com.google.inject.spi.Message;
 25import io.airlift.testing.Assertions;
 26import org.testng.Assert;
 27import org.testng.annotations.Test;
 28
 29import javax.validation.constraints.Max;
 30import javax.validation.constraints.Min;
 31import javax.validation.constraints.NotNull;
 32import java.util.List;
 33import java.util.Map;
 34import java.util.TreeMap;
 35
 36public class ConfigurationFactoryTest
 37{
 38
 39    @Test
 40    public void testAnnotatedGettersThrows()
 41    {
 42        Map<String, String> properties = new TreeMap<String, String>();
 43        properties.put("string-value", "some value");
 44        properties.put("boolean-value", "true");
 45        TestMonitor monitor = new TestMonitor();
 46        try {
 47            createInjector(properties, monitor, new Module()
 48            {
 49                public void configure(Binder binder)
 50                {
 51                    ConfigurationModule.bindConfig(binder).to(AnnotatedGetter.class);
 52                }
 53            });
 54
 55            Assert.fail("Expected an exception in object creation due to conflicting configuration");
 56        } catch (CreationException e) {
 57            monitor.assertNumberOfErrors(2);
 58            Assertions.assertContainsAllOf(e.getMessage(), "not a valid setter", "getStringValue") ;
 59            Assertions.assertContainsAllOf(e.getMessage(), "not a valid setter", "isBooleanValue") ;
 60        }
 61    }
 62
 63    @Test
 64    public void testAnnotatedSetters()
 65    {
 66        Map<String, String> properties = new TreeMap<String, String>();
 67        properties.put("string-value", "some value");
 68        properties.put("boolean-value", "true");
 69        TestMonitor monitor = new TestMonitor();
 70        Injector injector = createInjector(properties, monitor, new Module()
 71        {
 72            public void configure(Binder binder)
 73            {
 74                ConfigurationModule.bindConfig(binder).to(AnnotatedSetter.class);
 75            }
 76        });
 77        AnnotatedSetter annotatedSetter = injector.getInstance(AnnotatedSetter.class);
 78        monitor.assertNumberOfErrors(0);
 79        monitor.assertNumberOfWarnings(0);
 80        Assert.assertNotNull(annotatedSetter);
 81        Assert.assertEquals(annotatedSetter.getStringValue(), "some value");
 82        Assert.assertEquals(annotatedSetter.isBooleanValue(), true);
 83    }
 84
 85    @Test
 86    public void testConfigurationDespiteLegacyConfig()
 87    {
 88        Map<String, String> properties = new TreeMap<String, String>();
 89        properties.put("string-a", "this is a");
 90        properties.put("string-b", "this is b");
 91        TestMonitor monitor = new TestMonitor();
 92        Injector injector = createInjector(properties, monitor, new Module()
 93        {
 94            public void configure(Binder binder)
 95            {
 96                ConfigurationModule.bindConfig(binder).to(LegacyConfigPresent.class);
 97            }
 98        });
 99        LegacyConfigPresent legacyConfigPresent = injector.getInstance(LegacyConfigPresent.class);
100        monitor.assertNumberOfErrors(0);
101        monitor.assertNumberOfWarnings(0);
102        Assert.assertNotNull(legacyConfigPresent);
103        Assert.assertEquals(legacyConfigPresent.getStringA(), "this is a");
104        Assert.assertEquals(legacyConfigPresent.getStringB(), "this is b");
105    }
106
107    @Test
108    public void testConfigurationThroughLegacyConfig()
109    {
110        Map<String, String> properties = new TreeMap<String, String>();
111        properties.put("string-value", "this is a");
112        properties.put("string-b", "this is b");
113        TestMonitor monitor = new TestMonitor();
114        Injector injector = createInjector(properties, monitor, new Module()
115        {
116            public void configure(Binder binder)
117            {
118                ConfigurationModule.bindConfig(binder).to(LegacyConfigPresent.class);
119            }
120        });
121        LegacyConfigPresent legacyConfigPresent = injector.getInstance(LegacyConfigPresent.class);
122        monitor.assertNumberOfErrors(0);
123        monitor.assertNumberOfWarnings(1);
124        monitor.assertMatchingWarningRecorded("string-value", "replaced", "Use 'string-a'");
125        Assert.assertNotNull(legacyConfigPresent);
126        Assert.assertEquals(legacyConfigPresent.getStringA(), "this is a");
127        Assert.assertEquals(legacyConfigPresent.getStringB(), "this is b");
128    }
129
130    @Test
131    public void testConfigurationWithRedundantLegacyConfig()
132    {
133        Map<String, String> properties = new TreeMap<String, String>();
134        properties.put("string-value", "this is a");
135        properties.put("string-a", "this is a");
136        properties.put("string-b", "this is b");
137        TestMonitor monitor = new TestMonitor();
138        Injector injector = createInjector(properties, monitor, new Module()
139        {
140            public void configure(Binder binder)
141            {
142                ConfigurationModule.bindConfig(binder).to(LegacyConfigPresent.class);
143            }
144        });
145        LegacyConfigPresent legacyConfigPresent = injector.getInstance(LegacyConfigPresent.class);
146        monitor.assertNumberOfErrors(0);
147        monitor.assertNumberOfWarnings(1);
148        monitor.assertMatchingWarningRecorded("string-value", "replaced", "Use 'string-a'");
149        Assert.assertNotNull(legacyConfigPresent);
150        Assert.assertEquals(legacyConfigPresent.getStringA(), "this is a");
151        Assert.assertEquals(legacyConfigPresent.getStringB(), "this is b");
152    }
153
154    @Test
155    public void testConfigurationWithConflictingLegacyConfigThrows()
156    {
157        Map<String, String> properties = new TreeMap<String, String>();
158        properties.put("string-value", "this is the old value");
159        properties.put("string-a", "this is a");
160        properties.put("string-b", "this is b");
161        TestMonitor monitor = new TestMonitor();
162        try {
163            createInjector(properties, monitor, new Module()
164            {
165                public void configure(Binder binder)
166                {
167                    ConfigurationModule.bindConfig(binder).to(LegacyConfigPresent.class);
168                }
169            });
170
171            Assert.fail("Expected an exception in object creation due to conflicting configuration");
172        } catch (CreationException e) {
173            monitor.assertNumberOfErrors(1);
174            monitor.assertNumberOfWarnings(1);
175            monitor.assertMatchingWarningRecorded("string-value", "replaced", "Use 'string-a'");
176            Assertions.assertContainsAllOf(e.getMessage(), "string-value", "conflicts with property", "string-a") ;
177        }
178    }
179
180    @Test
181    public void testConfigurationDespiteDeprecatedConfig()
182    {
183        Map<String, String> properties = new TreeMap<String, String>();
184        properties.put("string-b", "this is b");
185        TestMonitor monitor = new TestMonitor();
186        Injector injector = createInjector(properties, monitor, new Module()
187        {
188            public void configure(Binder binder)
189            {
190                ConfigurationModule.bindConfig(binder).to(DeprecatedConfigPresent.class);
191            }
192        });
193        DeprecatedConfigPresent deprecatedConfigPresent = injector.getInstance(DeprecatedConfigPresent.class);
194        monitor.assertNumberOfErrors(0);
195        monitor.assertNumberOfWarnings(0);
196        Assert.assertNotNull(deprecatedConfigPresent);
197        Assert.assertEquals(deprecatedConfigPresent.getStringA(), "defaultA");
198        Assert.assertEquals(deprecatedConfigPresent.getStringB(), "this is b");
199    }
200
201    @Test
202    public void testConfigurationThroughDeprecatedConfig()
203    {
204        Map<String, String> properties = new TreeMap<String, String>();
205        properties.put("string-a", "this is a");
206        properties.put("string-b", "this is b");
207        TestMonitor monitor = new TestMonitor();
208        Injector injector = createInjector(properties, monitor, new Module()
209        {
210            public void configure(Binder binder)
211            {
212                ConfigurationModule.bindConfig(binder).to(DeprecatedConfigPresent.class);
213            }
214        });
215        DeprecatedConfigPresent deprecatedConfigPresent = injector.getInstance(DeprecatedConfigPresent.class);
216        monitor.assertNumberOfErrors(0);
217        monitor.assertNumberOfWarnings(1);
218        monitor.assertMatchingWarningRecorded("string-a", "deprecated and should not be used");
219        Assert.assertNotNull(deprecatedConfigPresent);
220        Assert.assertEquals(deprecatedConfigPresent.getStringA(), "this is a");
221        Assert.assertEquals(deprecatedConfigPresent.getStringB(), "this is b");
222    }
223
224    @Test
225    public void testDefunctPropertyInConfigThrows()
226    {
227        Map<String, String> properties = Maps.newTreeMap();
228        properties.put("string-value", "this is a");
229        properties.put("defunct-value", "this shouldn't work");
230        TestMonitor monitor = new TestMonitor();
231        try {
232            createInjector(properties, monitor, new Module()
233            {
234                public void configure(Binder binder)
235                {
236                    ConfigurationModule.bindConfig(binder).to(DefunctConfigPresent.class);
237                }
238            });
239
240            Assert.fail("Expected an exception in object creation due to use of defunct config");
241        } catch (CreationException e) {
242            monitor.assertNumberOfErrors(1);
243            monitor.assertNumberOfWarnings(0);
244            monitor.assertMatchingErrorRecorded("Defunct property", "'defunct-value", "cannot be configured");
245        }
246    }
247
248    @Test
249    public void testSuccessfulBeanValidation()
250    {
251        Map<String, String> properties = Maps.newHashMap();
252        properties.put("string-value", "has a value");
253        properties.put("int-value", "50");
254        TestMonitor monitor = new TestMonitor();
255        Injector injector = createInjector(properties, monitor, new Module()
256        {
257            public void configure(Binder binder)
258            {
259                ConfigurationModule.bindConfig(binder).to(BeanValidationClass.class);
260            }
261        });
262        BeanValidationClass beanValidationClass = injector.getInstance(BeanValidationClass.class);
263        monitor.assertNumberOfErrors(0);
264        monitor.assertNumberOfWarnings(0);
265        Assert.assertNotNull(beanValidationClass);
266        Assert.assertEquals(beanValidationClass.getStringValue(), "has a value");
267        Assert.assertEquals(beanValidationClass.getIntValue(), 50);
268    }
269
270    @Test
271    public void testFailedBeanValidation()
272    {
273        Map<String, String> properties = Maps.newHashMap();
274        // string-value left at invalid default
275        properties.put("int-value", "5000");  // out of range
276        TestMonitor monitor = new TestMonitor();
277        try {
278            Injector injector = createInjector(properties, monitor, new Module()
279            {
280                public void configure(Binder binder)
281                {
282                    ConfigurationModule.bindConfig(binder).to(BeanValidationClass.class);
283                }
284            });
285        } catch (CreationException e) {
286            monitor.assertNumberOfErrors(2);
287            monitor.assertNumberOfWarnings(0);
288            monitor.assertMatchingErrorRecorded("Constraint violation", "intValue", "must be less than or equal to 100", "BeanValidationClass");
289            monitor.assertMatchingErrorRecorded("Constraint violation", "stringValue", "may not be null", "BeanValidationClass");
290        }
291    }
292
293
294    private Injector createInjector(Map<String, String> properties, TestMonitor monitor, Module module)
295    {
296        ConfigurationFactory configurationFactory = new ConfigurationFactory(properties, monitor);
297        List<Message> messages = new ConfigurationValidator(configurationFactory, null).validate(module);
298        return Guice.createInjector(new ConfigurationModule(configurationFactory), module, new ValidationErrorModule(messages));
299    }
300
301
302    public static class AnnotatedGetter {
303        private String stringValue;
304        private boolean booleanValue;
305
306        @Config("string-value")
307        public String getStringValue()
308        {
309            return stringValue;
310        }
311
312        public void setStringValue(String stringValue)
313        {
314            this.stringValue = stringValue;
315        }
316
317        @Config("boolean-value")
318        public boolean isBooleanValue()
319        {
320            return booleanValue;
321        }
322
323        public void setBooleanValue(boolean booleanValue)
324        {
325            this.booleanValue = booleanValue;
326        }
327    }
328    
329    public static class AnnotatedSetter {
330        private String stringValue;
331        private boolean booleanValue;
332
333        public String getStringValue()
334        {
335            return stringValue;
336        }
337
338        @Config("string-value")
339        public void setStringValue(String stringValue)
340        {
341            this.stringValue = stringValue;
342        }
343
344        public boolean isBooleanValue()
345        {
346            return booleanValue;
347        }
348
349        @Config("boolean-value")
350        public void setBooleanValue(boolean booleanValue)
351        {
352            this.booleanValue = booleanValue;
353        }
354    }
355
356    public static class LegacyConfigPresent
357    {
358        private String stringA = "defaultA";
359        private String stringB = "defaultB";
360
361        public String getStringA()
362        {
363            return stringA;
364        }
365
366        @Config("string-a")
367        @LegacyConfig("string-value")
368        public void setStringA(String stringValue)
369        {
370            this.stringA = stringValue;
371        }
372
373        public String getStringB()
374        {
375            return stringB;
376        }
377
378        @Config("string-b")
379        public void setStringB(String stringValue)
380        {
381            this.stringB = stringValue;
382        }
383    }
384
385    public static class DeprecatedConfigPresent
386    {
387        private String stringA = "defaultA";
388        private String stringB = "defaultB";
389
390        @Deprecated
391        public String getStringA()
392        {
393            return stringA;
394        }
395
396        @Deprecated
397        @Config("string-a")
398        public void setStringA(String stringValue)
399        {
400            this.stringA = stringValue;
401        }
402
403        public String getStringB()
404        {
405            return stringB;
406        }
407
408        @Config("string-b")
409        public void setStringB(String stringValue)
410        {
411            this.stringB = stringValue;
412        }
413    }
414
415    @DefunctConfig("defunct-value")
416    public static class DefunctConfigPresent
417    {
418        private String stringValue;
419        private boolean booleanValue;
420
421        public String getStringValue()
422        {
423            return stringValue;
424        }
425
426        @Config("string-value")
427        public void setStringValue(String stringValue)
428        {
429            this.stringValue = stringValue;
430        }
431    }
432
433    public static class BeanValidationClass
434    {
435        @NotNull
436        private String stringValue = null;
437
438        private int myIntValue;
439
440        public String getStringValue()
441        {
442            return stringValue;
443        }
444
445        @Config("string-value")
446        public void setStringValue(String value)
447        {
448            this.stringValue = value;
449        }
450
451        @Min(1)
452        @Max(100)
453        public int getIntValue()
454        {
455            return myIntValue;
456        }
457
458        @Config("int-value")
459        public void setIntValue(int value)
460        {
461            this.myIntValue = value;
462        }
463    }
464}