### Question:
CounterMetricNameValidator extends AbstractMonitoringValidator<MetricDescriptor> { @Override public <T> List<ConstraintViolation<T>> validate( MonitoringValidationContext context, MetricDescriptor metricDescriptor, DescriptorPathImpl path) { Preconditions.checkNotNull(context); Preconditions.checkNotNull(metricDescriptor); if (!metricDescriptor.isCounter()) { return noViolations(); } path = constructPathFromProperty(metricDescriptor, "name", path); String metricName = metricDescriptor.getName(); if (!MonitoringConventions.isValidEndingForCounterMetric(metricName)) { String msg = String.format( "Counter metric '%s' ends with " + MonitoringConventions.RATE_SUFFIX, metricDescriptor.getName()); return forViolation(msg, metricDescriptor, metricName, path); } String userVisibleName = MonitoringConventions.convertCounterNameToUserFacingReadName( true, metricName); if (!MonitoringConventions.isValidMetricNameFormat(userVisibleName)) { String msg = String.format( "User visible name %s for counter metric '%s' does not a valid format", userVisibleName, metricDescriptor.getName()); return forViolation(msg, metricDescriptor, metricName, path); } if (context.metricsDefined.containsKey(userVisibleName)) { String msg = String.format( "User visible name %s for counter metric %s collides with a metric " + "defined in the MDL with the same name", userVisibleName, metricDescriptor.getName()); return forViolation(msg, metricDescriptor, metricName, path); } return noViolations(); }  @Override String getDescription(); @Override List<ConstraintViolation<T>> validate(
      MonitoringValidationContext context,
      MetricDescriptor metricDescriptor,
      DescriptorPathImpl path);  }### Answer:
@Test public void testGoodCounter() { setName("bytes_read"); assertTrue(validator.validate(context, metric, root).isEmpty()); }
@Test public void testCounterWithRateSuffix() { setName("bytes_read" + MonitoringConventions.RATE_SUFFIX); setIsCounter(true); List<ConstraintViolation<Object>> validations = validator.validate(context, metric, root); assertFalse(validations.isEmpty()); ConstraintViolation<Object> validation = Iterables.getOnlyElement( validations); assertTrue(validation.toString(), validation.getMessage().contains( "ends with _rate")); String path = validation.getPropertyPath().toString(); assertEquals(String.format("%s.name", SERVICE_NAME), path); }
@Test public void testNonCounterWithRateSuffix() { setName("bytes_read"); setIsCounter(false); assertTrue(validator.validate(context, metric, root).isEmpty()); }
@Test public void testCounterReadMetricInvalid() { setName("total__count"); setIsCounter(true); List<ConstraintViolation<Object>> validations = validator.validate(context, metric, root); assertFalse(validations.isEmpty()); ConstraintViolation<Object> validation = Iterables.getOnlyElement( validations); assertTrue(validation.toString(), validation.getMessage().contains( "visible name")); String path = validation.getPropertyPath().toString(); assertEquals(String.format("%s.name", SERVICE_NAME), path); }
@Test public void testCounterMetricVisibleNameCollidesWithExistingMetric() { setName("bytes_read"); setIsCounter(true); setServiceMetrics(ImmutableList.of(newMetricWithName("bytes_read_rate"))); context = new MonitoringValidationContext(serviceDescriptor); assertFalse(validator.validate(context, metric, root).isEmpty()); }