Java tutorial
/* * Copyright (c) 2012 by the original author * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.powertac.tariffmarket; import static org.junit.Assert.*; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Instant; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.powertac.common.Broker; import org.powertac.common.Competition; import org.powertac.common.CustomerInfo; import org.powertac.common.Rate; import org.powertac.common.RegulationCapacity; import org.powertac.common.RegulationRate; import org.powertac.common.Tariff; import org.powertac.common.TariffSpecification; import org.powertac.common.TariffSubscription; import org.powertac.common.TariffTransaction; import org.powertac.common.TimeService; import org.powertac.common.enumerations.PowerType; import org.powertac.common.interfaces.Accounting; import org.powertac.common.interfaces.BrokerProxy; import org.powertac.common.msg.BalancingControlEvent; import org.powertac.common.msg.BalancingOrder; import org.powertac.common.msg.EconomicControlEvent; import org.powertac.common.repo.TariffSubscriptionRepo; import org.powertac.common.repo.TimeslotRepo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Test cases for CapacityControlService * @author John Collins */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:tariff-test-config.xml" }) @DirtiesContext public class CapacityControlServiceTest { @Autowired private BrokerProxy mockProxy; @Autowired private TariffSubscriptionRepo tariffSubscriptionRepo; @Autowired private TimeService timeService; @Autowired private TimeslotRepo timeslotRepo; @Autowired private Accounting mockAccounting; @Autowired private CapacityControlService capacityControl; private Instant baseTime; private Broker broker; private CustomerInfo customer1; private CustomerInfo customer2; private TariffSpecification spec; private Tariff tariff; private List<Object> msgs = new ArrayList<Object>(); @Before public void setUp() throws Exception { reset(mockAccounting); baseTime = new DateTime(1972, 9, 6, 12, 0, 0, 0, DateTimeZone.UTC).toInstant(); timeService.setCurrentTime(baseTime); Competition competition = Competition.newInstance("tst").withSimulationBaseTime(baseTime); capacityControl.initialize(competition, new ArrayList<String>()); // set up some timeslots timeService.setCurrentTime(baseTime); timeslotRepo.makeTimeslot(baseTime); timeslotRepo.findOrCreateBySerialNumber(10); // broker and customers broker = new Broker("Jenny"); customer1 = new CustomerInfo("Podunk", 200).withPowerType(PowerType.INTERRUPTIBLE_CONSUMPTION); customer2 = new CustomerInfo("Nowhere", 400).withPowerType(PowerType.INTERRUPTIBLE_CONSUMPTION); // a tariff for interruptible consumption spec = new TariffSpecification(broker, PowerType.INTERRUPTIBLE_CONSUMPTION) .withExpiration(baseTime.plus(TimeService.DAY * 10)).withMinDuration(TimeService.DAY * 5) .addRate(new Rate().withValue(-0.11).withMaxCurtailment(0.4)); tariff = new Tariff(spec); tariff.init(); // mock the brokerProxyService, capturing the messages sent out msgs.clear(); doAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); msgs.add(args[1]); return null; } }).when(mockProxy).sendMessage(isA(Broker.class), anyObject()); } /** * Test method for {@link org.powertac.tariffmarket.CapacityControlService#postEconomicControl(org.powertac.common.msg.EconomicControlEvent)}. */ @Test public void testPostEconomicControl() { EconomicControlEvent ece1 = new EconomicControlEvent(spec, 0.20, 0); //EconomicControlEvent ece2 = new EconomicControlEvent(spec, 0.21, 1); EconomicControlEvent ece3 = new EconomicControlEvent(spec, 0.22, 2); EconomicControlEvent ece4 = new EconomicControlEvent(spec, 0.23, 3); assertNull("no controls ts 0", capacityControl.getControlsForTimeslot(0)); assertNull("no controls ts 1", capacityControl.getControlsForTimeslot(1)); capacityControl.postEconomicControl(ece1); List<EconomicControlEvent> controls = capacityControl.getControlsForTimeslot(0); assertNotNull("some controls ts 0", controls); assertEquals("one control", 1, controls.size()); assertEquals("correct control", ece1, controls.get(0)); assertNull("no controls ts 2", capacityControl.getControlsForTimeslot(2)); capacityControl.postEconomicControl(ece3); capacityControl.postEconomicControl(ece4); controls = capacityControl.getControlsForTimeslot(0); assertNotNull("some controls ts 0", controls); assertEquals("one control", 1, controls.size()); assertEquals("correct control", ece1, controls.get(0)); controls = capacityControl.getControlsForTimeslot(2); assertNotNull("some controls ts 2", controls); assertEquals("one control", 1, controls.size()); assertEquals("correct control", ece3, controls.get(0)); controls = capacityControl.getControlsForTimeslot(3); assertNotNull("some controls ts 3", controls); assertEquals("one control", 1, controls.size()); assertEquals("correct control", ece4, controls.get(0)); } // bogus control for past timeslot @Test public void postBogusEconomicControl() { timeService.setCurrentTime(timeService.getCurrentTime().plus(TimeService.HOUR)); EconomicControlEvent ece1 = new EconomicControlEvent(spec, 0.20, 0); capacityControl.postEconomicControl(ece1); List<EconomicControlEvent> controls = capacityControl.getControlsForTimeslot(0); assertNull("old timeslot, rejected", controls); EconomicControlEvent ece2 = new EconomicControlEvent(spec, 0.21, 1); capacityControl.postEconomicControl(ece2); controls = capacityControl.getControlsForTimeslot(1); assertNotNull("some controls ts 1", controls); assertEquals("one control", 1, controls.size()); assertEquals("correct control", ece2, controls.get(0)); } // check regulation capacity @Test public void regulationCapacity() { TariffSubscription sub1 = tariffSubscriptionRepo.getSubscription(customer1, tariff); sub1.subscribe(100); TariffSubscription sub2 = tariffSubscriptionRepo.getSubscription(customer2, tariff); sub2.subscribe(200); sub1.usePower(200); sub2.usePower(300); BalancingOrder order = new BalancingOrder(broker, spec, 1.0, 0.1); RegulationCapacity cap = capacityControl.getRegulationCapacity(order); assertEquals("correct up-regulation", 0.4 * 500.0, cap.getUpRegulationCapacity(), 1e-6); assertEquals("correct down-regulation", 0.0, cap.getDownRegulationCapacity(), 1e-6); } // check regulation capacity with regulation-rates @Test public void regulationCapacityRegRate() { TariffSpecification specRR = new TariffSpecification(broker, PowerType.INTERRUPTIBLE_CONSUMPTION) .withExpiration(baseTime.plus(TimeService.DAY * 10)).withMinDuration(TimeService.DAY * 5) .addRate(new Rate().withValue(-0.11)) .addRate(new RegulationRate().withUpRegulationPayment(0.15).withDownRegulationPayment(-0.05)); Tariff tariffRR = new Tariff(specRR); tariffRR.init(); TariffSubscription sub1 = tariffSubscriptionRepo.getSubscription(customer1, tariffRR); sub1.subscribe(100); TariffSubscription sub2 = tariffSubscriptionRepo.getSubscription(customer2, tariffRR); sub2.subscribe(200); sub1.setRegulationCapacity(new RegulationCapacity(sub1, 3.0, -1.5)); sub1.usePower(200); sub2.setRegulationCapacity(new RegulationCapacity(sub2, 2.0, -1.1)); sub2.usePower(300); BalancingOrder order = new BalancingOrder(broker, specRR, 1.0, 0.1); RegulationCapacity cap = capacityControl.getRegulationCapacity(order); assertEquals("correct up-regulation", 700.0, cap.getUpRegulationCapacity(), 1e-6); assertEquals("correct down-regulation", -370.0, cap.getDownRegulationCapacity(), 1e-6); } /** * Up-regulation test */ @Test public void testExerciseBalancingControlUp() { TariffSubscription sub1 = tariffSubscriptionRepo.getSubscription(customer1, tariff); sub1.subscribe(100); TariffSubscription sub2 = tariffSubscriptionRepo.getSubscription(customer2, tariff); sub2.subscribe(200); sub1.usePower(200); sub2.usePower(300); BalancingOrder order = new BalancingOrder(broker, spec, 1.0, 0.1); RegulationCapacity cap = capacityControl.getRegulationCapacity(order); assertEquals("correct up-regulation", 0.4 * 500.0, cap.getUpRegulationCapacity(), 1e-6); assertEquals("correct down-regulation", 0.0, cap.getDownRegulationCapacity(), 1e-6); // exercise the control assertEquals("no messages yet", 0, msgs.size()); reset(mockAccounting); final HashMap<CustomerInfo, Object[]> answers = new HashMap<CustomerInfo, Object[]>(); when(mockAccounting.addTariffTransaction(any(TariffTransaction.Type.class), any(Tariff.class), any(CustomerInfo.class), anyInt(), anyDouble(), anyDouble())).thenAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); CustomerInfo customer = (CustomerInfo) args[2]; answers.put(customer, args); return null; } }); capacityControl.exerciseBalancingControl(order, 100.0, 11.0); // check the outgoing message assertEquals("one message", 1, msgs.size()); assertTrue("correct type", msgs.get(0) instanceof BalancingControlEvent); BalancingControlEvent bce = (BalancingControlEvent) msgs.get(0); assertEquals("correct broker", broker, bce.getBroker()); assertEquals("correct tariff", spec.getId(), bce.getTariffId()); assertEquals("correct amount", 100.0, bce.getKwh(), 1e-6); assertEquals("correct payment", 11.0, bce.getPayment(), 1e-6); assertEquals("correct timeslot", 0, bce.getTimeslotIndex()); // Check regulation assertEquals("correct regulation sub1", 40.0 / 100.0, sub1.getRegulation(), 1e-6); assertEquals("correct regulation sub2", 60.0 / 200.0, sub2.getRegulation(), 1e-6); // check tariff transactions assertEquals("correct # of calls", 2, answers.size()); Object[] args = answers.get(customer1); assertNotNull("customer1 included", args); assertEquals("correct arg count", 6, args.length); assertEquals("correct type", TariffTransaction.Type.PRODUCE, (TariffTransaction.Type) args[0]); assertEquals("correct tariff", tariff, (Tariff) args[1]); assertEquals("correct kwh", 40.0, (Double) args[4], 1e-6); assertEquals("correct charge", -4.4, (Double) args[5], 1e-6); args = answers.get(customer2); assertNotNull("customer2 included", args); assertEquals("correct arg count", 6, args.length); assertEquals("correct type", TariffTransaction.Type.PRODUCE, (TariffTransaction.Type) args[0]); assertEquals("correct tariff", tariff, (Tariff) args[1]); assertEquals("correct kwh", 60.0, (Double) args[4], 1e-6); assertEquals("correct charge", -6.6, (Double) args[5], 1e-6); } /** * Up-regulation test */ @Test public void testExerciseBalancingControlDown() { TariffSpecification specRR1 = new TariffSpecification(broker, PowerType.THERMAL_STORAGE_CONSUMPTION) .addRate(new Rate().withValue(-0.11)) .addRate(new RegulationRate().withUpRegulationPayment(0.15).withDownRegulationPayment(-0.05)); Tariff tariffRR1 = new Tariff(specRR1); tariffRR1.init(); TariffSubscription sub1 = tariffSubscriptionRepo.getSubscription(customer1, tariffRR1); sub1.subscribe(100); sub1.setRegulationCapacity(new RegulationCapacity(sub1, 3.0, -1.5)); sub1.usePower(200); // avail down-regulation is -150 TariffSubscription sub2 = tariffSubscriptionRepo.getSubscription(customer2, tariffRR1); sub2.subscribe(200); sub2.setRegulationCapacity(new RegulationCapacity(sub2, 2.0, -1.1)); sub2.usePower(300); // avail down-regulation is -220 BalancingOrder order = new BalancingOrder(broker, specRR1, -1.0, -0.04); RegulationCapacity cap = capacityControl.getRegulationCapacity(order); assertEquals("correct up-regulation", 700.0, cap.getUpRegulationCapacity(), 1e-6); assertEquals("correct down-regulation", -370.0, cap.getDownRegulationCapacity(), 1e-6); // exercise the control assertEquals("no messages yet", 0, msgs.size()); reset(mockAccounting); final HashMap<CustomerInfo, Object[]> answers = new HashMap<CustomerInfo, Object[]>(); when(mockAccounting.addTariffTransaction(any(TariffTransaction.Type.class), any(Tariff.class), any(CustomerInfo.class), anyInt(), anyDouble(), anyDouble())).thenAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); CustomerInfo customer = (CustomerInfo) args[2]; answers.put(customer, args); return null; } }); capacityControl.exerciseBalancingControl(order, -100.0, -6.0); // check the outgoing message assertEquals("one message", 1, msgs.size()); assertTrue("correct type", msgs.get(0) instanceof BalancingControlEvent); BalancingControlEvent bce = (BalancingControlEvent) msgs.get(0); assertEquals("correct broker", broker, bce.getBroker()); assertEquals("correct tariff", specRR1.getId(), bce.getTariffId()); assertEquals("correct amount", -100.0, bce.getKwh(), 1e-6); assertEquals("correct payment", -6.0, bce.getPayment(), 1e-6); assertEquals("correct timeslot", 0, bce.getTimeslotIndex()); // Check regulation assertEquals("correct regulation sub1", -15000.0 / 370.0 / 100.0, sub1.getRegulation(), 1e-6); assertEquals("correct regulation sub2", -22000.0 / 370.0 / 200.0, sub2.getRegulation(), 1e-6); // check tariff transactions assertEquals("correct # of calls", 2, answers.size()); Object[] args = answers.get(customer1); assertNotNull("customer1 included", args); assertEquals("correct arg count", 6, args.length); assertEquals("correct type", TariffTransaction.Type.CONSUME, (TariffTransaction.Type) args[0]); assertEquals("correct tariff", tariffRR1, (Tariff) args[1]); assertEquals("correct kwh", -15000.0 / 370.0, (Double) args[4], 1e-6); assertEquals("correct charge", 0.05 * 15000.0 / 370.0, (Double) args[5], 1e-6); args = answers.get(customer2); assertNotNull("customer2 included", args); assertEquals("correct arg count", 6, args.length); assertEquals("correct type", TariffTransaction.Type.CONSUME, (TariffTransaction.Type) args[0]); assertEquals("correct tariff", tariffRR1, (Tariff) args[1]); assertEquals("correct kwh", -22000.0 / 370.0, (Double) args[4], 1e-6); assertEquals("correct charge", 0.05 * 22000.0 / 370.0, (Double) args[5], 1e-6); } /** * Test method for {@link org.powertac.tariffmarket.CapacityControlService#activate(org.joda.time.Instant, int)}. */ @Test public void testActivate() { // set up subscriptions TariffSubscription sub1 = tariffSubscriptionRepo.getSubscription(customer1, tariff); sub1.subscribe(100); TariffSubscription sub2 = tariffSubscriptionRepo.getSubscription(customer2, tariff); sub2.subscribe(200); // post a couple of economic controls EconomicControlEvent ece0 = new EconomicControlEvent(spec, 0.20, 0); EconomicControlEvent ece1 = new EconomicControlEvent(spec, 0.25, 1); capacityControl.postEconomicControl(ece0); capacityControl.postEconomicControl(ece1); // activate the capacity control capacityControl.activate(timeService.getCurrentTime(), 1); // capture calls to Accounting reset(mockAccounting); final HashMap<CustomerInfo, Object[]> answers = new HashMap<CustomerInfo, Object[]>(); when(mockAccounting.addTariffTransaction(any(TariffTransaction.Type.class), any(Tariff.class), any(CustomerInfo.class), anyInt(), anyDouble(), anyDouble())).thenAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); CustomerInfo customer = (CustomerInfo) args[2]; answers.put(customer, args); return null; } }); // now the customer model is primed. Both customers should be curtailed // by 20% in this timeslot. sub1.usePower(200); sub2.usePower(300); assertEquals("correct # of calls", 2, answers.size()); Object[] args = answers.get(customer1); assertNotNull("customer1 included", args); assertEquals("correct arg count", 6, args.length); assertEquals("correct type", TariffTransaction.Type.CONSUME, (TariffTransaction.Type) args[0]); assertEquals("correct tariff", tariff, (Tariff) args[1]); assertEquals("correct kwh", -160.0, (Double) args[4], 1e-6); assertEquals("correct charge", 160.0 * 0.11, (Double) args[5], 1e-6); args = answers.get(customer2); assertNotNull("customer2 included", args); assertEquals("correct arg count", 6, args.length); assertEquals("correct type", TariffTransaction.Type.CONSUME, (TariffTransaction.Type) args[0]); assertEquals("correct tariff", tariff, (Tariff) args[1]); assertEquals("correct kwh", -240.0, (Double) args[4], 1e-6); assertEquals("correct charge", 240.0 * 0.11, (Double) args[5], 1e-6); // check regulation info assertEquals("correct regulation sub1", 40.0, sub1.getCurtailment(), 1e-6); assertEquals("correct regulation sub1", 60.0, sub2.getCurtailment(), 1e-6); } }