/reporting/src/test/java/com/proofpoint/reporting/TestReportBinder.java

https://github.com/ssindkar/platform · Java · 918 lines · 811 code · 92 blank · 15 comment · 2 complexity · 58797e62c7eee7d24903944565bd7d43 MD5 · raw file

  1. /*
  2. * Copyright 2013 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 com.proofpoint.reporting;
  17. import com.google.common.collect.ImmutableList;
  18. import com.google.common.collect.ImmutableMap;
  19. import com.google.common.collect.ImmutableSet;
  20. import com.google.common.collect.ImmutableSet.Builder;
  21. import com.google.inject.Binder;
  22. import com.google.inject.CreationException;
  23. import com.google.inject.Guice;
  24. import com.google.inject.Injector;
  25. import com.google.inject.Key;
  26. import com.google.inject.Module;
  27. import com.google.inject.Provides;
  28. import com.google.inject.ProvisionException;
  29. import com.google.inject.Scopes;
  30. import com.google.inject.name.Names;
  31. import com.google.inject.util.Modules;
  32. import com.proofpoint.reporting.ReportedBeanRegistry.RegistrationInfo;
  33. import org.testng.annotations.Test;
  34. import org.weakref.jmx.Flatten;
  35. import org.weakref.jmx.Managed;
  36. import org.weakref.jmx.Nested;
  37. import javax.inject.Qualifier;
  38. import javax.inject.Singleton;
  39. import javax.management.MalformedObjectNameException;
  40. import javax.management.ObjectName;
  41. import javax.validation.constraints.NotNull;
  42. import java.lang.annotation.Annotation;
  43. import java.lang.annotation.Retention;
  44. import java.lang.annotation.RetentionPolicy;
  45. import java.util.Collection;
  46. import java.util.Map;
  47. import java.util.Optional;
  48. import java.util.Set;
  49. import static com.google.common.collect.Iterables.getOnlyElement;
  50. import static com.google.inject.multibindings.Multibinder.newSetBinder;
  51. import static com.proofpoint.reporting.BucketIdProvider.BucketId.bucketId;
  52. import static com.proofpoint.reporting.ReportBinder.reportBinder;
  53. import static org.mockito.ArgumentMatchers.any;
  54. import static org.mockito.Mockito.spy;
  55. import static org.mockito.Mockito.verify;
  56. import static org.testng.Assert.assertEquals;
  57. import static org.testng.Assert.fail;
  58. public class TestReportBinder
  59. {
  60. private static final TestingAnnotation TESTING_ANNOTATION = new TestingAnnotation()
  61. {
  62. @Override
  63. public Class<? extends Annotation> annotationType()
  64. {
  65. return TestingAnnotation.class;
  66. }
  67. };
  68. private final ObjectName testingClassName;
  69. public TestReportBinder()
  70. throws MalformedObjectNameException
  71. {
  72. testingClassName = ObjectName.getInstance("com.example:type=TestingClass,name=TestingAnnotation");
  73. Guice.createInjector(new TestingModule());
  74. }
  75. @Test
  76. public void testGauge() {
  77. Injector injector = Guice.createInjector(
  78. new TestingModule(),
  79. binder -> {
  80. reportBinder(binder).export(GaugeClass.class);
  81. });
  82. assertReportRegistration(injector, false, "GaugeClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  83. }
  84. @Test
  85. public void testGaugeWithAnnotationClass() {
  86. Injector injector = Guice.createInjector(
  87. new TestingModule(),
  88. binder -> {
  89. reportBinder(binder).export(GaugeClass.class).annotatedWith(TestingAnnotation.class);
  90. });
  91. assertReportRegistration(injector, false, "GaugeClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  92. }
  93. @Test
  94. public void testGaugeWithNameAnnotation() {
  95. Injector injector = Guice.createInjector(
  96. new TestingModule(),
  97. binder -> {
  98. reportBinder(binder).export(GaugeClass.class).annotatedWith(Names.named("TestingAnnotation"));
  99. });
  100. assertReportRegistration(injector, false, "GaugeClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  101. }
  102. @Test
  103. public void testGaugeWithAnnotation() {
  104. Injector injector = Guice.createInjector(
  105. new TestingModule(),
  106. binder -> {
  107. reportBinder(binder).export(GaugeClass.class).annotatedWith(TESTING_ANNOTATION);
  108. });
  109. assertReportRegistration(injector, false, "GaugeClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  110. }
  111. @SuppressWarnings("deprecation")
  112. @Test
  113. public void testGaugeWithLegacyName() {
  114. Injector injector = Guice.createInjector(
  115. new TestingModule(),
  116. binder -> {
  117. reportBinder(binder).export(GaugeClass.class).as(testingClassName.getCanonicalName());
  118. });
  119. assertReportRegistration(injector, false, "TestingClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  120. }
  121. @Test
  122. public void testGaugeKey() {
  123. Injector injector = Guice.createInjector(
  124. new TestingModule(),
  125. binder -> {
  126. reportBinder(binder).export(Key.get(GaugeClass.class));
  127. });
  128. assertReportRegistration(injector, false, "GaugeClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  129. }
  130. @Test
  131. public void testGaugeKeyWithAnnotationClass() {
  132. Injector injector = Guice.createInjector(
  133. new TestingModule(),
  134. binder -> {
  135. reportBinder(binder).export(Key.get(GaugeClass.class, TestingAnnotation.class));
  136. });
  137. assertReportRegistration(injector, false, "GaugeClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  138. }
  139. @Test
  140. public void testGaugeKeyWithNameAnnotation() {
  141. Injector injector = Guice.createInjector(
  142. new TestingModule(),
  143. binder -> {
  144. reportBinder(binder).export(Key.get(GaugeClass.class, Names.named("TestingAnnotation")));
  145. });
  146. assertReportRegistration(injector, false, "GaugeClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  147. }
  148. @Test
  149. public void testGaugeKeyWithAnnotation() {
  150. Injector injector = Guice.createInjector(
  151. new TestingModule(),
  152. binder -> {
  153. reportBinder(binder).export(Key.get(GaugeClass.class, TESTING_ANNOTATION));
  154. });
  155. assertReportRegistration(injector, false, "GaugeClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  156. }
  157. @SuppressWarnings("deprecation")
  158. @Test
  159. public void testGaugeKeyWithLegacyName() {
  160. Injector injector = Guice.createInjector(
  161. new TestingModule(),
  162. binder -> {
  163. reportBinder(binder).export(Key.get(GaugeClass.class)).as(testingClassName.getCanonicalName());
  164. });
  165. assertReportRegistration(injector, false, "TestingClass.TestingAnnotation", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  166. }
  167. @Test
  168. public void testGaugeWithNamePrefix() {
  169. Injector injector = Guice.createInjector(
  170. new TestingModule(),
  171. binder -> {
  172. reportBinder(binder).export(GaugeClass.class).withNamePrefix("TestingNamePrefix");
  173. });
  174. assertReportRegistration(injector, false, "TestingNamePrefix", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  175. }
  176. @Test
  177. public void testGaugeWithTags() {
  178. Injector injector = Guice.createInjector(
  179. new TestingModule(),
  180. binder -> {
  181. reportBinder(binder).export(GaugeClass.class).withTags(ImmutableMap.of("foo", "bar", "baz", "quux"));
  182. });
  183. assertReportRegistration(injector, false, "GaugeClass", ImmutableMap.of("foo", "bar", "baz", "quux"), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  184. }
  185. @Test
  186. public void testGaugeWithNamePrefixAndTags() {
  187. Injector injector = Guice.createInjector(
  188. new TestingModule(),
  189. binder -> {
  190. reportBinder(binder).export(GaugeClass.class).withNamePrefix("TestingNamePrefix").withTags(ImmutableMap.of("foo", "bar", "baz", "quux"));
  191. });
  192. assertReportRegistration(injector, false, "TestingNamePrefix", ImmutableMap.of("foo", "bar", "baz", "quux"), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  193. }
  194. @Test
  195. public void testGaugeWithApplicationPrefix() {
  196. Injector injector = Guice.createInjector(
  197. new TestingModule(),
  198. binder -> {
  199. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix();
  200. });
  201. assertReportRegistration(injector, true, "GaugeClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  202. }
  203. @Test
  204. public void testGaugeWithApplicationAndNamePrefix() {
  205. Injector injector = Guice.createInjector(
  206. new TestingModule(),
  207. binder -> {
  208. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withNamePrefix("TestingNamePrefix");
  209. });
  210. assertReportRegistration(injector, true, "TestingNamePrefix", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  211. }
  212. @Test
  213. public void testGaugeWithApplicationPrefixAndTags() {
  214. Injector injector = Guice.createInjector(
  215. new TestingModule(),
  216. binder -> {
  217. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withTags(ImmutableMap.of("foo", "bar", "baz", "quux"));
  218. });
  219. assertReportRegistration(injector, true, "GaugeClass", ImmutableMap.of("foo", "bar", "baz", "quux"), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  220. }
  221. @Test
  222. public void testGaugeWithApplicationAndNamePrefixAndTags() {
  223. Injector injector = Guice.createInjector(
  224. new TestingModule(),
  225. binder -> {
  226. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withNamePrefix("TestingNamePrefix").withTags(ImmutableMap.of("foo", "bar", "baz", "quux"));
  227. });
  228. assertReportRegistration(injector, true, "TestingNamePrefix", ImmutableMap.of("foo", "bar", "baz", "quux"), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  229. }
  230. @Test
  231. public void testReportedOnly() {
  232. Injector injector = Guice.createInjector(
  233. new TestingModule(),
  234. binder -> {
  235. reportBinder(binder).export(ReportedClass.class);
  236. });
  237. assertReportRegistration(injector, false, "ReportedClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Reported")));
  238. }
  239. @Test
  240. public void testManagedOnly() {
  241. Injector injector = Guice.createInjector(
  242. new TestingModule(),
  243. binder -> {
  244. reportBinder(binder).export(ManagedClass.class);
  245. });
  246. assertNoReportRegistration(injector);
  247. }
  248. @Test
  249. public void testNested() {
  250. Injector injector = Guice.createInjector(
  251. new TestingModule(),
  252. binder -> {
  253. reportBinder(binder).export(NestedClass.class);
  254. });
  255. injector.getInstance(NestedClass.class);
  256. assertReportRegistration(injector, false, "NestedClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Nested.Gauge", "Nested.Reported")));
  257. }
  258. @Test
  259. public void testFlatten() {
  260. Injector injector = Guice.createInjector(
  261. new TestingModule(),
  262. binder -> {
  263. reportBinder(binder).export(FlattenClass.class);
  264. });
  265. assertReportRegistration(injector, false, "FlattenClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  266. }
  267. @Test
  268. public void testBucketed() {
  269. Injector injector = Guice.createInjector(
  270. new TestingModule(),
  271. binder -> {
  272. reportBinder(binder).export(BucketedClass.class);
  273. });
  274. BucketedClass.assertProviderSupplied(injector.getInstance(BucketedClass.class));
  275. assertReportRegistration(injector, false, "BucketedClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  276. }
  277. @Test
  278. public void testNestedBucketed() {
  279. Injector injector = Guice.createInjector(
  280. new TestingModule(),
  281. binder -> {
  282. reportBinder(binder).export(NestedBucketedClass.class);
  283. });
  284. BucketedClass.assertProviderSupplied(injector.getInstance(NestedBucketedClass.class));
  285. BucketedClass.assertProviderSupplied(injector.getInstance(NestedBucketedClass.class).getNested());
  286. assertReportRegistration(injector, false, "NestedBucketedClass", ImmutableMap.of(), Optional.of(ImmutableSet.of(
  287. "Gauge", "Reported",
  288. "Nested.Gauge", "Nested.Reported"
  289. )));
  290. }
  291. @Test
  292. public void testFlattenBucketed() {
  293. Injector injector = Guice.createInjector(
  294. new TestingModule(),
  295. binder -> {
  296. reportBinder(binder).export(FlattenBucketedClass.class);
  297. });
  298. BucketedClass.assertProviderSupplied(injector.getInstance(FlattenBucketedClass.class).getFlatten());
  299. assertReportRegistration(injector, false, "FlattenBucketedClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  300. }
  301. @Test
  302. public void testDeepBucketed() {
  303. Injector injector = Guice.createInjector(
  304. new TestingModule(),
  305. binder -> {
  306. reportBinder(binder).export(DeepBucketedClass.class);
  307. });
  308. BucketedClass.assertProviderSupplied(injector.getInstance(DeepBucketedClass.class).getNested());
  309. BucketedClass.assertProviderSupplied(injector.getInstance(DeepBucketedClass.class).getFlatten());
  310. BucketedClass.assertProviderSupplied(injector.getInstance(DeepBucketedClass.class).getFlatten().getNested());
  311. assertReportRegistration(injector, false, "DeepBucketedClass", ImmutableMap.of(), Optional.of(ImmutableSet.of(
  312. "Gauge", "Reported",
  313. "Nested.Gauge", "Nested.Reported"
  314. )));
  315. }
  316. @Test
  317. public void testDuplicate() {
  318. Injector injector = Guice.createInjector(
  319. new TestingModule(),
  320. binder -> {
  321. reportBinder(binder).export(GaugeClass.class);
  322. reportBinder(binder).export(GaugeClass.class);
  323. });
  324. assertReportRegistration(injector, false, "GaugeClass", ImmutableMap.of(), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  325. }
  326. @Test
  327. public void testDuplicateAllFeatures() {
  328. Injector injector = Guice.createInjector(
  329. new TestingModule(),
  330. binder -> {
  331. reportBinder(binder).export(GaugeClass.class).annotatedWith(TestingAnnotation.class).withApplicationPrefix().withNamePrefix("Prefix").withTags(ImmutableMap.of("foo", "bar"));
  332. reportBinder(binder).export(GaugeClass.class).annotatedWith(TestingAnnotation.class).withApplicationPrefix().withNamePrefix("Prefix").withTags(ImmutableMap.of("foo", "bar"));
  333. });
  334. assertReportRegistration(injector, true, "Prefix", ImmutableMap.of("foo", "bar"), Optional.of(ImmutableSet.of("Gauge", "Reported")));
  335. }
  336. @Test(expectedExceptions = ReportException.class)
  337. public void testDuplicateDifferentApplicationPrefixThrows()
  338. throws Throwable
  339. {
  340. try {
  341. Guice.createInjector(
  342. new TestingModule(),
  343. binder -> {
  344. reportBinder(binder).export(GaugeClass.class).withNamePrefix("Prefix").withTags(ImmutableMap.of("foo", "bar"));
  345. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withNamePrefix("Prefix").withTags(ImmutableMap.of("foo", "bar"));
  346. });
  347. fail("Expected CreationException");
  348. } catch (CreationException e) {
  349. throw e.getCause();
  350. }
  351. }
  352. @Test(expectedExceptions = ReportException.class)
  353. public void testDuplicateDifferentNamePrefixThrows()
  354. throws Throwable
  355. {
  356. try {
  357. Guice.createInjector(
  358. new TestingModule(),
  359. binder -> {
  360. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withNamePrefix("Prefix").withTags(ImmutableMap.of("foo", "bar"));
  361. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withNamePrefix("Other").withTags(ImmutableMap.of("foo", "bar"));
  362. });
  363. fail("Expected CreationException");
  364. } catch (CreationException e) {
  365. throw e.getCause();
  366. }
  367. }
  368. @Test(expectedExceptions = ReportException.class)
  369. public void testDuplicateDifferentTagsThrows()
  370. throws Throwable
  371. {
  372. try {
  373. Guice.createInjector(
  374. new TestingModule(),
  375. binder -> {
  376. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withNamePrefix("Prefix").withTags(ImmutableMap.of("foo", "bar"));
  377. reportBinder(binder).export(GaugeClass.class).withApplicationPrefix().withNamePrefix("Prefix");
  378. });
  379. fail("Expected CreationException");
  380. } catch (CreationException e) {
  381. throw e.getCause();
  382. }
  383. }
  384. @Test(expectedExceptions = ReportException.class)
  385. public void testDuplicateDifferentAnnotationThrows()
  386. throws Throwable
  387. {
  388. try {
  389. GaugeClass gaugeClass = new GaugeClass();
  390. Guice.createInjector(
  391. Modules.override(new TestingModule()).with(
  392. binder -> {
  393. binder.bind(GaugeClass.class).toInstance(gaugeClass);
  394. binder.bind(GaugeClass.class).annotatedWith(TestingAnnotation.class).toInstance(gaugeClass);
  395. reportBinder(binder).export(GaugeClass.class);
  396. reportBinder(binder).export(GaugeClass.class).annotatedWith(TestingAnnotation.class);
  397. }));
  398. fail("Expected CreationException");
  399. } catch (CreationException e) {
  400. throw e.getCause();
  401. }
  402. }
  403. @Test
  404. public void testReportCollectionDefaultName()
  405. {
  406. Injector injector = Guice.createInjector(
  407. new TestingCollectionModule(),
  408. binder -> {
  409. reportBinder(binder).bindReportCollection(KeyedDistribution.class);
  410. }
  411. );
  412. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  413. keyedDistribution.add("value", false);
  414. assertReportRegistration(injector, false, "KeyedDistribution.Add", ImmutableMap.of("foo", "value", "bar", "false"), Optional.empty());
  415. }
  416. @Test
  417. public void testReportCollectionWithAnnotationClass()
  418. {
  419. Injector injector = Guice.createInjector(
  420. new TestingCollectionModule(),
  421. binder -> {
  422. reportBinder(binder).bindReportCollection(KeyedDistribution.class).annotatedWith(TestingAnnotation.class);
  423. });
  424. KeyedDistribution keyedDistribution = injector.getInstance(Key.get(KeyedDistribution.class, TestingAnnotation.class));
  425. keyedDistribution.add("value", false);
  426. assertReportRegistration(injector, false, "KeyedDistribution.Add", ImmutableMap.of("foo", "value", "bar", "false"), Optional.empty());
  427. }
  428. @Test
  429. public void testReportCollectionWithAnnotation()
  430. {
  431. Injector injector = Guice.createInjector(
  432. new TestingCollectionModule(),
  433. binder -> {
  434. reportBinder(binder).bindReportCollection(KeyedDistribution.class).annotatedWith(TESTING_ANNOTATION);
  435. });
  436. KeyedDistribution keyedDistribution = injector.getInstance(Key.get(KeyedDistribution.class, TESTING_ANNOTATION));
  437. keyedDistribution.add("value", false);
  438. assertReportRegistration(injector, false, "KeyedDistribution.Add", ImmutableMap.of("foo", "value", "bar", "false"), Optional.empty());
  439. }
  440. @Test
  441. public void testReportCollectionWithNamePrefix()
  442. {
  443. Injector injector = Guice.createInjector(
  444. new TestingCollectionModule(),
  445. binder -> {
  446. reportBinder(binder).bindReportCollection(KeyedDistribution.class).withNamePrefix("TestingNamePrefix");
  447. }
  448. );
  449. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  450. keyedDistribution.add("value", false);
  451. assertReportRegistration(injector, false, "TestingNamePrefix.Add", ImmutableMap.of("foo", "value", "bar", "false"), Optional.empty());
  452. }
  453. @Test
  454. public void testReportCollectionWithNullNamePrefix()
  455. {
  456. Injector injector = Guice.createInjector(
  457. new TestingCollectionModule(),
  458. binder -> {
  459. reportBinder(binder).bindReportCollection(KeyedDistribution.class).withNamePrefix(null);
  460. }
  461. );
  462. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  463. keyedDistribution.add("value", false);
  464. assertReportRegistration(injector, false, "Add", ImmutableMap.of("foo", "value", "bar", "false"), Optional.empty());
  465. }
  466. @Test
  467. public void testReportCollectionWithTags()
  468. {
  469. Injector injector = Guice.createInjector(
  470. new TestingCollectionModule(),
  471. binder -> {
  472. reportBinder(binder).bindReportCollection(KeyedDistribution.class).withTags(ImmutableMap.of("a", "bar", "b", "quux"));
  473. }
  474. );
  475. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  476. keyedDistribution.add("value", false);
  477. assertReportRegistration(injector, false, "KeyedDistribution.Add", ImmutableMap.of("foo", "value", "bar", "false", "a", "bar", "b", "quux"), Optional.empty());
  478. }
  479. @Test(expectedExceptions = ProvisionException.class,
  480. expectedExceptionsMessageRegExp = ".*KeyedDistribution\\.add\\(java\\.lang\\.String, boolean\\) @Key\\(\"foo\"\\) duplicates tag on entire report collection.*")
  481. public void testReportCollectionWithConflictingTags()
  482. {
  483. Injector injector = Guice.createInjector(
  484. new TestingCollectionModule(),
  485. binder -> {
  486. reportBinder(binder).bindReportCollection(KeyedDistribution.class).withTags(ImmutableMap.of("foo", "bar"));
  487. }
  488. );
  489. injector.getInstance(KeyedDistribution.class);
  490. }
  491. @Test
  492. public void testReportCollectionWithNamePrefixAndTags()
  493. {
  494. Injector injector = Guice.createInjector(
  495. new TestingCollectionModule(),
  496. binder -> {
  497. reportBinder(binder).bindReportCollection(KeyedDistribution.class)
  498. .withNamePrefix("TestingNamePrefix")
  499. .withTags(ImmutableMap.of("a", "bar", "b", "quux"));
  500. }
  501. );
  502. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  503. keyedDistribution.add("value", false);
  504. assertReportRegistration(injector, false, "TestingNamePrefix.Add", ImmutableMap.of("foo", "value", "bar", "false", "a", "bar", "b", "quux"), Optional.empty());
  505. }
  506. @Test
  507. public void testReportCollectionWithApplicationPrefix()
  508. {
  509. Injector injector = Guice.createInjector(
  510. new TestingCollectionModule(),
  511. binder -> {
  512. reportBinder(binder).bindReportCollection(KeyedDistribution.class).withApplicationPrefix();
  513. }
  514. );
  515. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  516. keyedDistribution.add("value", false);
  517. assertReportRegistration(injector, true, "KeyedDistribution.Add", ImmutableMap.of("foo", "value", "bar", "false"), Optional.empty());
  518. }
  519. @Test
  520. public void testReportCollectionWithApplicationAndNamePrefix()
  521. {
  522. Injector injector = Guice.createInjector(
  523. new TestingCollectionModule(),
  524. binder -> {
  525. reportBinder(binder).bindReportCollection(KeyedDistribution.class)
  526. .withApplicationPrefix()
  527. .withNamePrefix("TestingNamePrefix");
  528. }
  529. );
  530. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  531. keyedDistribution.add("value", false);
  532. assertReportRegistration(injector, true, "TestingNamePrefix.Add", ImmutableMap.of("foo", "value", "bar", "false"), Optional.empty());
  533. }
  534. @Test
  535. public void testReportCollectionWithApplicationPrefixAndTags()
  536. {
  537. Injector injector = Guice.createInjector(
  538. new TestingCollectionModule(),
  539. binder -> {
  540. reportBinder(binder).bindReportCollection(KeyedDistribution.class)
  541. .withApplicationPrefix()
  542. .withTags(ImmutableMap.of("a", "bar", "b", "quux"));
  543. }
  544. );
  545. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  546. keyedDistribution.add("value", false);
  547. assertReportRegistration(injector, true, "KeyedDistribution.Add", ImmutableMap.of("foo", "value", "bar", "false", "a", "bar", "b", "quux"), Optional.empty());
  548. }
  549. @Test
  550. public void testReportCollectionWithApplicationAndNamePrefixAndTags()
  551. {
  552. Injector injector = Guice.createInjector(
  553. new TestingCollectionModule(),
  554. binder -> {
  555. reportBinder(binder).bindReportCollection(KeyedDistribution.class)
  556. .withApplicationPrefix()
  557. .withNamePrefix("TestingNamePrefix")
  558. .withTags(ImmutableMap.of("a", "bar", "b", "quux"));
  559. }
  560. );
  561. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  562. keyedDistribution.add("value", false);
  563. assertReportRegistration(injector, true, "TestingNamePrefix.Add", ImmutableMap.of("foo", "value", "bar", "false", "a", "bar", "b", "quux"), Optional.empty());
  564. }
  565. @SuppressWarnings("deprecation")
  566. @Test
  567. public void testReportCollectionWithLegacyName()
  568. {
  569. Injector injector = Guice.createInjector(
  570. new TestingCollectionModule(),
  571. binder -> {
  572. reportBinder(binder).bindReportCollection(KeyedDistribution.class).as("com.example:type=\"Foo\\\",Bar\",a=b");
  573. });
  574. KeyedDistribution keyedDistribution = injector.getInstance(KeyedDistribution.class);
  575. keyedDistribution.add("value", false);
  576. assertReportRegistration(injector, false, "Foo\",Bar.Add", ImmutableMap.of("foo", "value", "bar", "false", "a", "b"), Optional.empty());
  577. }
  578. @SuppressWarnings("deprecation")
  579. @Test
  580. public void testReportCollectionWithLegacyNameAndAnnotation()
  581. {
  582. Injector injector = Guice.createInjector(
  583. new TestingCollectionModule(),
  584. binder -> {
  585. reportBinder(binder).bindReportCollection(KeyedDistribution.class).annotatedWith(TestingAnnotation.class).as("com.example:type=\"Foo\\\",Bar\",a=b");
  586. });
  587. KeyedDistribution keyedDistribution = injector.getInstance(Key.get(KeyedDistribution.class, TestingAnnotation.class));
  588. keyedDistribution.add("value", false);
  589. assertReportRegistration(injector, false, "Foo\",Bar.Add", ImmutableMap.of("foo", "value", "bar", "false", "a", "b"), Optional.empty());
  590. }
  591. @SuppressWarnings("deprecation")
  592. @Test
  593. public void testReportCollectionLegacyNameAndNameAnnotated()
  594. {
  595. Injector injector = Guice.createInjector(
  596. new TestingCollectionModule(),
  597. binder -> {
  598. reportBinder(binder).bindReportCollection(KeyedDistribution.class).annotatedWith(Names.named("testing")).as("com.example:type=\"Foo\\\",Bar\",a=b");
  599. });
  600. KeyedDistribution keyedDistribution = injector.getInstance(Key.get(KeyedDistribution.class, Names.named("testing")));
  601. keyedDistribution.add("value", false);
  602. assertReportRegistration(injector, false, "Foo\",Bar.Add", ImmutableMap.of("foo", "value", "bar", "false", "a", "b"), Optional.empty());
  603. }
  604. private void assertNoReportRegistration(Injector injector)
  605. {
  606. ReportedBeanRegistry reportedBeanRegistry = injector.getInstance(ReportedBeanRegistry.class);
  607. assertEquals(reportedBeanRegistry.getReportedBeans(), ImmutableList.<RegistrationInfo>of());
  608. }
  609. private void assertReportRegistration(Injector injector, boolean applicationPrefix, String namePrefix, Map<String, String> tags, Optional<Set<String>> expectedAttributes)
  610. {
  611. ReportedBeanRegistry reportedBeanRegistry = injector.getInstance(ReportedBeanRegistry.class);
  612. RegistrationInfo registrationInfo = getOnlyElement(reportedBeanRegistry.getReportedBeans());
  613. assertEquals(registrationInfo.isApplicationPrefix(), applicationPrefix);
  614. assertEquals(registrationInfo.getNamePrefix(), namePrefix, "name prefix");
  615. assertEquals(registrationInfo.getTags(), tags, "tags");
  616. if (expectedAttributes.isPresent()) {
  617. Collection<ReportedBeanAttribute> attributes = registrationInfo.getReportedBean().getAttributes();
  618. assertAttributes(attributes, expectedAttributes.get());
  619. }
  620. }
  621. private void assertAttributes(Collection<ReportedBeanAttribute> attributes, Set<String> expected)
  622. {
  623. Builder<String> builder = ImmutableSet.builder();
  624. for (ReportedBeanAttribute attribute : attributes) {
  625. String name = attribute.getName();
  626. builder.add(name);
  627. }
  628. assertEquals(builder.build(), expected);
  629. }
  630. public static class GaugeClass {
  631. @Gauge
  632. public int getGauge()
  633. {
  634. return 1;
  635. }
  636. @Reported
  637. public int getReported()
  638. {
  639. return 2;
  640. }
  641. @Managed
  642. public int getManaged()
  643. {
  644. return 3;
  645. }
  646. }
  647. private static class ReportedClass {
  648. @Reported
  649. public int getReported()
  650. {
  651. return 2;
  652. }
  653. }
  654. private static class ManagedClass {
  655. @Managed
  656. public int getManaged()
  657. {
  658. return 3;
  659. }
  660. }
  661. public static class NestedClass {
  662. private final GaugeClass nested = new GaugeClass();
  663. @Nested
  664. public GaugeClass getNested()
  665. {
  666. return nested;
  667. }
  668. }
  669. public static class FlattenClass {
  670. private final GaugeClass flatten = new GaugeClass();
  671. @Flatten
  672. public GaugeClass getFlatten()
  673. {
  674. return flatten;
  675. }
  676. }
  677. private static class TestingModule implements Module
  678. {
  679. @Override
  680. public void configure(Binder binder)
  681. {
  682. binder.requireExplicitBindings();
  683. binder.disableCircularProxies();
  684. binder.bind(GaugeClass.class).in(Scopes.SINGLETON);
  685. binder.bind(GaugeClass.class).annotatedWith(TestingAnnotation.class).to(GaugeClass.class).in(Scopes.SINGLETON);
  686. binder.bind(GaugeClass.class).annotatedWith(Names.named("TestingAnnotation")).to(GaugeClass.class).in(Scopes.SINGLETON);
  687. binder.bind(GaugeClass.class).annotatedWith(TESTING_ANNOTATION).to(GaugeClass.class).in(Scopes.SINGLETON);
  688. binder.bind(ReportedClass.class).in(Scopes.SINGLETON);
  689. binder.bind(ManagedClass.class).in(Scopes.SINGLETON);
  690. binder.bind(NestedClass.class).in(Scopes.SINGLETON);
  691. binder.bind(FlattenClass.class).in(Scopes.SINGLETON);
  692. binder.bind(FlattenBucketedClass.class).in(Scopes.SINGLETON);
  693. binder.bind(ReportExporter.class).asEagerSingleton();
  694. binder.bind(GuiceReportExporter.class).asEagerSingleton();
  695. newSetBinder(binder, Mapping.class);
  696. binder.bind(ReportedBeanRegistry.class).in(Scopes.SINGLETON);
  697. }
  698. @Provides
  699. @Singleton
  700. BucketedClass getBucketedClass()
  701. {
  702. return BucketedClass.createBucketedClass();
  703. }
  704. @Provides
  705. @Singleton
  706. NestedBucketedClass getNestedBucketedClass()
  707. {
  708. return NestedBucketedClass.createNestedBucketedClass();
  709. }
  710. @Provides
  711. @Singleton
  712. DeepBucketedClass getDeepBucketedClass()
  713. {
  714. return DeepBucketedClass.createDeepBucketedClass();
  715. }
  716. @Provides
  717. @Singleton
  718. BucketIdProvider getBucketIdProvider()
  719. {
  720. return () -> bucketId(0, 0);
  721. }
  722. }
  723. private static class TestingCollectionModule implements Module
  724. {
  725. @Override
  726. public void configure(Binder binder)
  727. {
  728. binder.requireExplicitBindings();
  729. binder.disableCircularProxies();
  730. binder.bind(ReportCollectionFactory.class).in(Scopes.SINGLETON);
  731. binder.bind(ReportExporter.class).asEagerSingleton();
  732. newSetBinder(binder, Mapping.class);
  733. binder.bind(ReportedBeanRegistry.class).in(Scopes.SINGLETON);
  734. }
  735. @Provides
  736. @Singleton
  737. BucketIdProvider getBucketIdProvider()
  738. {
  739. return () -> bucketId(0, 0);
  740. }
  741. }
  742. @Retention(RetentionPolicy.RUNTIME)
  743. @Qualifier
  744. private @interface TestingAnnotation
  745. {}
  746. private static class BucketedClass
  747. extends Bucketed<GaugeClass>
  748. {
  749. private BucketedClass()
  750. {
  751. }
  752. static BucketedClass createBucketedClass()
  753. {
  754. return spy(new BucketedClass());
  755. }
  756. @Override
  757. protected GaugeClass createBucket(GaugeClass previousBucket)
  758. {
  759. return new GaugeClass();
  760. }
  761. public static void assertProviderSupplied(BucketedClass mock)
  762. {
  763. verify(mock).setBucketIdProvider(any(BucketIdProvider.class));
  764. }
  765. }
  766. private static class NestedBucketedClass
  767. extends BucketedClass
  768. {
  769. private BucketedClass nested = createBucketedClass();
  770. private NestedBucketedClass()
  771. {
  772. }
  773. private static NestedBucketedClass createNestedBucketedClass()
  774. {
  775. return spy(new NestedBucketedClass());
  776. }
  777. @Nested
  778. BucketedClass getNested()
  779. {
  780. return nested;
  781. }
  782. }
  783. private static class FlattenBucketedClass
  784. {
  785. private BucketedClass flatten = BucketedClass.createBucketedClass();
  786. @Flatten
  787. private BucketedClass getFlatten()
  788. {
  789. return flatten;
  790. }
  791. }
  792. private static class DeepBucketedClass
  793. {
  794. private NestedBucketedClass flatten = NestedBucketedClass.createNestedBucketedClass();
  795. private BucketedClass nested = BucketedClass.createBucketedClass();
  796. private DeepBucketedClass()
  797. {
  798. }
  799. private static DeepBucketedClass createDeepBucketedClass()
  800. {
  801. return spy(new DeepBucketedClass());
  802. }
  803. @Flatten
  804. private NestedBucketedClass getFlatten()
  805. {
  806. return flatten;
  807. }
  808. @Nested
  809. BucketedClass getNested()
  810. {
  811. return nested;
  812. }
  813. }
  814. private interface KeyedDistribution
  815. {
  816. SomeObject add(@com.proofpoint.reporting.Key("foo") String key, @NotNull @com.proofpoint.reporting.Key("bar") boolean bool);
  817. }
  818. public static class SomeObject
  819. {
  820. @Reported
  821. private int getValue()
  822. {
  823. return 0;
  824. }
  825. }
  826. }