bool isCompatible(const ScheduleTypeLimits &parentLimits,
                  const ScheduleTypeLimits &candidate)
{
  if (candidate == parentLimits) {
    return true;
  }

  // check continuous/discrete
  if (OptionalString numericType = parentLimits.numericType()) {
    if (!candidate.numericType() || !istringEqual(candidate.numericType().get(),*numericType)) {
      return false;
    }
  }

  // check unit type
  std::string unitType = parentLimits.unitType();
  if (parentLimits.isUnitTypeDefaulted() || istringEqual("Dimensionless",unitType)) {
    if (!(candidate.isUnitTypeDefaulted() || (istringEqual("Dimensionless",candidate.unitType())))) {
      return false;
    }
  }
  else {
    if (!istringEqual(candidate.unitType(),unitType)) {
      return false;
    }
  }

  // check lower limit
  if (parentLimits.lowerLimitValue()) {
    if (!candidate.lowerLimitValue() ||
        (candidate.lowerLimitValue().get() < parentLimits.lowerLimitValue().get()))
    {
      return false;
    }
  }

  // check upper limit
  if (parentLimits.upperLimitValue()) {
    if (!candidate.upperLimitValue() ||
        (candidate.upperLimitValue().get() > parentLimits.upperLimitValue().get()))
    {
      return false;
    }
  }

  // passed all checks
  return true;
}
TEST_F(ModelFixture, ScheduleTypeRegistry_UseInSetSchedule) {
  Model model;

  // create a schedule
  ScheduleConstant schedule(model);

  // set a minimal schedule type limits
  ScheduleTypeLimits anyNumber(model);
  anyNumber.setName("Any Number");
  bool ok = schedule.setScheduleTypeLimits(anyNumber);
  EXPECT_TRUE(ok);

  // try to set Lights schedule--should fail b/c needs between 0 and 1
  LightsDefinition definition(model);
  definition.setLightingLevel(100.0);
  Lights light(definition);
  ok = light.setSchedule(schedule);
  EXPECT_FALSE(ok);

  // set Availablity schedule type limits
  ScheduleType scheduleType = ScheduleTypeRegistry::instance().getScheduleType("CoilCoolingDXSingleSpeed","Availability");
  ScheduleTypeLimits availabilityLimits = ScheduleTypeRegistry::instance().getOrCreateScheduleTypeLimits(scheduleType,model);
  ok = schedule.setScheduleTypeLimits(availabilityLimits);
  EXPECT_TRUE(ok);

  // try to set Lights schedule--used to fail b/c lights schedule is Dimensionless, not Availability, now passes
  ok = light.setSchedule(schedule);
  EXPECT_TRUE(ok);

  // clear conflicting information
  availabilityLimits.resetNumericType();
  availabilityLimits.resetUnitType();

  // set Lights schedule--should succeed b/c not in conflict
  ok = light.setSchedule(schedule);
  EXPECT_TRUE(ok);

  // try to clear schedule type limits--should fail b/c in use
  ok = schedule.resetScheduleTypeLimits();
  EXPECT_FALSE(ok);

  // reset Lights schedule
  light.resetSchedule();

  // try to clear schedule type limits--should succeed
  ok = schedule.resetScheduleTypeLimits();
  EXPECT_TRUE(ok);
  EXPECT_FALSE(schedule.scheduleTypeLimits());

  // set Lights schedule--should succeed and assign an appropriate ScheduleTypeLimits
  ok = light.setSchedule(schedule);
  EXPECT_TRUE(ok);
  ASSERT_TRUE(schedule.scheduleTypeLimits());
  ScheduleTypeLimits lightsLimits = schedule.scheduleTypeLimits().get();
  EXPECT_EQ("Fractional",lightsLimits.name().get());
  ASSERT_TRUE(lightsLimits.numericType());
  EXPECT_EQ("Continuous",lightsLimits.numericType().get());
  EXPECT_EQ("Dimensionless",lightsLimits.unitType());
  EXPECT_TRUE(lightsLimits.isUnitTypeDefaulted());
  ASSERT_TRUE(lightsLimits.lowerLimitValue());
  EXPECT_DOUBLE_EQ(0.0,lightsLimits.lowerLimitValue().get());
  ASSERT_TRUE(lightsLimits.upperLimitValue());
  EXPECT_DOUBLE_EQ(1.0,lightsLimits.upperLimitValue().get());
}