OptaPlanner: Nullable Planning Variable not working as expected - drools

I am trying to solve a Berth and Crane Allocation problem to incoming vessels. I need to assign multiple berths and multiple cranes to the incoming vessel and I created a ResourceAsisgnment planning entity class for the same.
#PlanningEntity
public class ResourceAssignment {
private Berth myberth;
// planning variables
private Vessel myVessel;
private QC myCrane;
// no args constructor on planning entity required by Optaplanner
public ResourceAssignment () {}
// constructor with args for initializing the class
public ResourceAssignment(Berth myBerth) {
this.myberth = myBerth;
}
#PlanningVariable(valueRangeProviderRefs = { "AvailableVessels" }, nullable = true)
public Vessel getMyVessel() {
return myVessel;
}
public void setMyVessel(Vessel myVessel) {
this.myVessel = myVessel;
}
#PlanningVariable(valueRangeProviderRefs = { "AvailableCranes" }, nullable = true)
public QC getMyCrane() {
return myCrane;
}
public void setMyCrane(QC myCrane) {
this.myCrane = myCrane;
}
public Berth getMyberth() {
return myberth;
}
public void setMyberth(Berth myberth) {
this.myberth = myberth;
}
}
I am initializing the class with berth data, hence I am essentially assigning berths to vessels and QCs.
I have a hard rule that states if a vessel is being assigned anything less than its required number of berths (which is a class attribute for the vessel) it has to be penalized. This rule is also considering the vessels that are not being assigned any berths, which I don't want to consider. It is ok for a vessel to not be assigned any berths but it cant get less than what is the require number of berths- which is why I set
nullable = true on the vessel.
This is how my rule looks:
rule "no assigning below the number of berths required"
salience 1
when
$vessel: Vessel($vesselName:vesselName, $berthsRequired: berthsRequired)
$berthsAssignedToVessel : Number(intValue<$berthsRequired) from accumulate(
ResourceAssignment(myVessel!=null, myVessel == $vessel),
count(1)
)
then
int distanceToBerths = Math.abs($berthsAssignedToVessel.intValue() - $berthsRequired);
scoreHolder.addHardConstraintMatch(kcontext, -distanceToBerths);
end
I am not sure if the rule definition is wrong but the rule is being broken and it is also penalizing vessels that are not being assigned any berths.
Please help me on how I can resolve this issue.

Related

Can Kaitai Struct be used to describe TLV data without creating new types for each field?

I'm reverse engineering a file format that stores each field as TLV blocks (type, length, value).
The fields do not have to be in order, or even present at all. Their presence is denoted with a sentinel, which is a 16-bit type identifier and a 32-bit end offset. There are hundreds of unique identifiers, but a decent chunk of those are just single primitive values. aside from denoting the type, they can also identify what field the data should be stored in.
It is also worth noting that there will never be a duplicate id on a parent structure. The only time is can occur is if there are multiple of the same object type in an array/list.
I have successfully written a Kaitai definition for one of them:
meta:
id: struct_02ea
endian: le
seq:
- id: unk_00
type: s4
- id: fields
type: field_block
repeat: eos
types:
sentinel:
seq:
- id: id
type: u2
- id: end_offset
type: u4
field_block:
seq:
- id: sentinel
type: sentinel
- id: value
type:
switch-on: sentinel.id
cases:
0xF0: u1
0xF1: u1
0xF2: u1
0xF3: u1
0xF4: u4
0xF5: u4
size: sentinel.end_offset - _root._io.pos
Handling things this way does work, and I could likely map out the entire format like this. However, when it comes time to compiling this definition into another format, things get nasty.
Since I am wrapping each field in a field_block, the generated code stores these values in that type of object. This is incredibly inefficient when half of the generated field_block objects store a single integer. It would also require the consuming code to iterate through a list of each field block in order to get the actual field's value.
Ideally, I would like to define this structure so that the sentinels are only parsed while Kaitai is reading the data, and each value would be mapped to a field on the parent structure.
Is this possible? This technology is really cool, and I'd love to use it in my project, but I feel like the overhead that this is generating is a lot more trouble than it's worth.
Here's an example of the definition when compiled into C#:
using System.Collections.Generic;
namespace Kaitai
{
public partial class Struct02ea : KaitaiStruct
{
public static Struct02ea FromFile(string fileName)
{
return new Struct02ea(new KaitaiStream(fileName));
}
public Struct02ea(KaitaiStream p__io, KaitaiStruct p__parent = null, Struct02ea p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root ?? this;
_read();
}
private void _read()
{
_unk00 = m_io.ReadS4le();
_fields = new List<FieldBlock>();
{
var i = 0;
while (!m_io.IsEof) {
_fields.Add(new FieldBlock(m_io, this, m_root));
i++;
}
}
}
public partial class Sentinel : KaitaiStruct
{
public static Sentinel FromFile(string fileName)
{
return new Sentinel(new KaitaiStream(fileName));
}
public Sentinel(KaitaiStream p__io, Struct02ea.FieldBlock p__parent = null, Struct02ea p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_id = m_io.ReadU2le();
_endOffset = m_io.ReadU4le();
}
private ushort _id;
private uint _endOffset;
private Struct02ea m_root;
private Struct02ea.FieldBlock m_parent;
public ushort Id { get { return _id; } }
public uint EndOffset { get { return _endOffset; } }
public Struct02ea M_Root { get { return m_root; } }
public Struct02ea.FieldBlock M_Parent { get { return m_parent; } }
}
public partial class FieldBlock : KaitaiStruct
{
public static FieldBlock FromFile(string fileName)
{
return new FieldBlock(new KaitaiStream(fileName));
}
public FieldBlock(KaitaiStream p__io, Struct02ea p__parent = null, Struct02ea p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_sentinel = new Sentinel(m_io, this, m_root);
switch (Sentinel.Id) {
case 243: {
_value = m_io.ReadU1();
break;
}
case 244: {
_value = m_io.ReadU4le();
break;
}
case 245: {
_value = m_io.ReadU4le();
break;
}
case 241: {
_value = m_io.ReadU1();
break;
}
case 240: {
_value = m_io.ReadU1();
break;
}
case 242: {
_value = m_io.ReadU1();
break;
}
default: {
_value = m_io.ReadBytes((Sentinel.EndOffset - M_Root.M_Io.Pos));
break;
}
}
}
private Sentinel _sentinel;
private object _value;
private Struct02ea m_root;
private Struct02ea m_parent;
public Sentinel Sentinel { get { return _sentinel; } }
public object Value { get { return _value; } }
public Struct02ea M_Root { get { return m_root; } }
public Struct02ea M_Parent { get { return m_parent; } }
}
private int _unk00;
private List<FieldBlock> _fields;
private Struct02ea m_root;
private KaitaiStruct m_parent;
public int Unk00 { get { return _unk00; } }
public List<FieldBlock> Fields { get { return _fields; } }
public Struct02ea M_Root { get { return m_root; } }
public KaitaiStruct M_Parent { get { return m_parent; } }
}
}
Affiliate disclaimer: I'm a Kaitai Struct maintainer (see my GitHub profile).
Since I am wrapping each field in a field_block, the generated code stores these values in that type of object. This is incredibly inefficient when half of the generated field_block objects store a single integer. It would also require the consuming code to iterate through a list of each field block in order to get the actual field's value.
I think that rather than trying to describe the entire format with an ultimate Kaitai Struct specification, it's better for you not to let the generated code parse all the fields automatically. Move the parsing control to your application code, where you use the type Struct02ea.FieldBlock that represents the individual field and basically replicate the "repeat until end of stream" loop that the generated code that you posted was doing:
_fields = new List<FieldBlock>();
{
var i = 0;
while (!m_io.IsEof) {
_fields.Add(new FieldBlock(m_io, this, m_root));
i++;
}
}
The advantage of doing so is that you can adjust the loop to fit your needs. To avoid the overhead you describe, you'll probably want to keep the Struct02ea.FieldBlock object in a local variable inside the loop body, pull only the values you care about (save them in your compact, consumer-friendly output structures) and let it leave the scope after the loop iteration ends. This will allow each original FieldBlock object to get garbage-collected once you process it, so the overhead they have will be limited to a single instance and not multiplied by the number of fields in the file.
The most straightforward and seamless way to prevent the Kaitai Struct-generated code parse fields (but otherwise keep everything the same) is to add if: false in the KSY specification, as #webbnh suggested in a GitHub issue:
seq:
- id: unk_00
type: s4
- id: fields
type: field_block
repeat: eos
if: false # add this
The if: false works better than omitting it from seq entirely, because the kaitai-struct-compiler has occasional troubles with unused types (when compiling the KSY spec with unused types, you may get an error "Unable to derive _parent type in ..." due to a compiler bug). But with this if: false trick, you can't run into them because the field_block type is no longer unused.

How to optimize SQL query in Anylogic

I am generating Agents with parameter values coming from SQL table in Anylogic. when agent is generated at source I am doing a v look up in table and extracting corresponding values from table. For now it is working perfectly but it is slowing down the performance.
Structure of Table looks like this
I am querying the data from this table with below code
double value_1 = (selectFrom(account_details)
.where(account_details.act_code.eq(z))
.list(account_details.avg_value)).get(0);
double value_min = (selectFrom(account_details)
.where(account_details.act_code.eq(z))
.list(account_details.min_value)).get(0);
double value_max = (selectFrom(account_details)
.where(account_details.act_code.eq(z))
.list(account_details.max_value)).get(0);
// Fetch the cluster number from account table
int cluster_num = (selectFrom(account_details)
.where(account_details.act_code.eq(z))
.list(account_details.cluster)).get(0);
int act_no = (selectFrom(account_details)
.where(account_details.act_code.eq(z))
.list(account_details.actno)).get(0);
String pay_term = (selectFrom(account_details)
.where(account_details.act_code.eq(z))
.list(account_details.pay_term)).get(0);
String pay_term_prob = (selectFrom(account_details)
.where(account_details.act_code.eq(z))
.list(account_details.pay_term_prob)).get(0);
But this is very slow and wants to improve the performance. someone mentioned that we can create a Java class and then add the table into collection . Is there any example where I can refer. I am finding it difficult to put entire code.
I have created a class using below code:
public class Customer {
private String act_code;
private int actno;
private double avg_value;
private String pay_term;
private String pay_term_prob;
private int cluster;
private double min_value;
private double max_value;
public String getact_code() {
return act_code;
}
public void setact_code(String act_code) {
this.act_code = act_code;
}
public int getactno() {
return actno;
}
public void setactno(int actno) {
this.actno = actno;
}
public double getavg_value() {
return avg_value;
}
public void setavg_value(double avg_value) {
this.avg_value = avg_value;
}
public String getpay_term() {
return pay_term;
}
public void setpay_term(String pay_term) {
this.pay_term = pay_term;
}
public String getpay_term_prob() {
return pay_term_prob;
}
public void setpay_term_prob(String pay_term_prob) {
this.pay_term_prob = pay_term_prob;
}
public int cluster() {
return cluster;
}
public void setcluster(int cluster) {
this.cluster = cluster;
}
public double getmin_value() {
return min_value;
}
public void setmin_value(double min_value) {
this.min_value = min_value;
}
public double getmax_value() {
return max_value;
}
public void setmax_value(double max_value) {
this.max_value = max_value;
}
}
Created collection object like this:
Pls provide an reference to add this database table into collection as a next step. then I want to query the collection based on the condition
You are on the right track here!
Every time you access the database to read data there is a computational overhead. So the best option is to access the database only once, at the start of the model. Create all the objects you need, store other data you will need later into Java classes, and then use the Java classes.
My suggestion is to create a Java class for each row in your table, like you have done. And then create a map object - like you have done, but with the key as String and the value as this new object.
Then on model start you can populate this map as follows:
List<Tuple> rows = selectFrom(customer).list();
for (Tuple row : rows) {
Customer customerData = new Customer(
row.get( customer.act_code ),
row.get( customer.actno ),
row.get( customer.avg_value )
);
mapOfCustomerData.put(customerData.act_code, customerData);
}
Where mapOfCustomerData is a linkedHashMap and customer is the name of the table
See the model created in this blog post for more details and an example on using a scenario object to store all the data from the Database in a separate object
Note: The code above is just an example - read this blog post for more details on using the AnyLogic INternal Database
Before using Java classes, try this first: click the "index" tickbox for all columns that you query with a WHERE clause.

Update facts in Decision Table : Drools

I have a drools decision table in excel spreadsheet with two rules. (This example has been greatly simplified, the one I am working with has alot more rules.)
The first rule checks if amount is more than or equal to 500. If it is, then it sets status to 400.
The second rule checks if status is 400. If it is, then it sets the message variable.
The problem is, I am unable to get the second rule to fire, even though sequential is set. I also have to use no-loop and lock-on-active to prevent infinite looping.
My goal is to get the rules to fire top down, and the rules that come after might depend on changes made to the fact/object by earlier rules.
Is there a solution to this problem?
Any help would be appreciated, thanks!
package com.example;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
public class SalaryTest {
public static final void main(String[] args) {
try {
// load up the knowledge base
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-dtables");
Salary a = new Salary();
a.setAmount(600);
kSession.insert(a);
kSession.fireAllRules();
} catch (Throwable t) {
t.printStackTrace();
}
}
public static class Salary{
private String message;
private int amount;
private int status;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
}
The attribute lock-on-active countermands any firings after the first from the group of rules with the same agenda group. Remove this column.
Don't plan to have rules firing in a certain order. Write logic that describes exactly the state of a fact as it should trigger the rule. Possibly you'll have to write
rule "set status"
when
$s: Salary( amount >= 500.0 && < 600.0, status == 0 )
then
modify( $s ){ setStatus( 400 ) }
end
to avoid more than one status setting to happen or just the right setting to happen. But you'll find that your rules may be more outspoken and easier to read.
Think of rule attributes are a last resort.
Please replace the action in the column H in the following way:
Current solution:
a.setStatus($param);update(a);
New solution:
modify(a) {
setStatus($param)
}

Nullpointer exception in CompositePlanningValueRangeDescriptor.extractValues

I'm facing a NPE when trying to solve my solution:
Exception in thread "main" java.lang.NullPointerException
at java.util.ArrayList.addAll(ArrayList.java:472)
at org.drools.planner.core.domain.variable.CompositePlanningValueRangeDescriptor.extractValues(CompositePlanningValueRangeDescriptor.java:46)
at org.drools.planner.core.domain.variable.PlanningVariableDescriptor.extractPlanningValues(PlanningVariableDescriptor.java:259)
at org.drools.planner.core.heuristic.selector.variable.PlanningValueSelector.initSelectedPlanningValueList(PlanningValueSelector.java:91)
at org.drools.planner.core.heuristic.selector.variable.PlanningValueSelector.phaseStarted(PlanningValueSelector.java:73)
at org.drools.planner.core.heuristic.selector.variable.PlanningValueWalker.phaseStarted(PlanningValueWalker.java:64)
at org.drools.planner.core.heuristic.selector.variable.PlanningVariableWalker.phaseStarted(PlanningVariableWalker.java:62)
at org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.phaseStarted(DefaultGreedyDecider.java:62)
at org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.phaseStarted(DefaultGreedyFitSolverPhase.java:112)
at org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:57)
at org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:190)
at org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:155)
at de.haw.dsms.applicationcore.planning.BalancingApp.main(BalancingApp.java:47)
I have annotated my planning entity with the following annotations to collect the value range from two lists in the solution:
#PlanningEntity
public class ScheduleItem implements Cloneable{
private ChangeOfferEvent item;
#PlanningVariable()
#ValueRanges({
#ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY, solutionProperty = "offers"),
#ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY, solutionProperty = "dummies")
})
public ChangeOfferEvent getItem() {
return item;
}
public void setItem(ChangeOfferEvent item) {
this.item = item;
}
public ScheduleItem() {
this.item = null;
}
...
This is the solution:
public class ProductionConsumptionBalancing implements Solution<HardAndSoftLongScore> {
/*
* Problem facts
*/
// The grid entity offers
private List<ChangeOfferEvent> offers;
// Placeholder events to represent "not used schedule items"
private List<PlaceholderOfferEvent> dummies;
// The total energy consumption in the grid
// [Watt]
private TotalEnergyConsumption totalElectricityConsumption;
// The total energy production in the grid
// [Watt]
private TotalEnergyProduction totalElectricityProduction;
public List<ChangeOfferEvent> getOffers() {
return offers;
}
public void setOffers(List<ChangeOfferEvent> offers) {
this.offers = offers;
}
public List<PlaceholderOfferEvent> getDummies() {
return dummies;
}
public void setDummies(List<PlaceholderOfferEvent> dummies) {
this.dummies = dummies;
}
public TotalEnergyConsumption getTotalElectricityConsumption() {
return totalElectricityConsumption;
}
public void setTotalElectricityConsumption(
TotalEnergyConsumption totalElectricityConsumption) {
this.totalElectricityConsumption = totalElectricityConsumption;
}
public TotalEnergyProduction getTotalElectricityProduction() {
return totalElectricityProduction;
}
public void setTotalElectricityProduction(
TotalEnergyProduction totalElectricityProduction) {
this.totalElectricityProduction = totalElectricityProduction;
}
/*
* Problem entities
*/
private List<ScheduleItem> schedule;
#PlanningEntityCollectionProperty
public List<ScheduleItem> getSchedule() {
return schedule;
}
public void setSchedule(List<ScheduleItem> schedule) {
this.schedule = schedule;
}
...
The strange thing about this is, that during debugging I discoverd that it is the parameter "planningEntity" which is null and not the values in the solution.
Does anybody encounter the same issue or does know how to solve this?
Thanks and best regards!
PS:
It seems like this is coming from the method initSelectedPlanningValueList:
private void initSelectedPlanningValueList(AbstractSolverPhaseScope phaseScope) {
90 if (planningVariableDescriptor.isPlanningValuesCacheable()) {
91 Collection<?> planningValues = planningVariableDescriptor.extractPlanningValues(
92 phaseScope.getWorkingSolution(), null);
93 cachedPlanningValues = applySelectionOrder(planningValues);
94 } else {
95 cachedPlanningValues = null;
96 }
97 }
PSPS:
Problem solved.
The issue appeared because I forgot to link the clone's dummies-attribute to the original dummies list. So the dummies list in the cloned solution was null.
#Override
public Solution<HardAndSoftLongScore> cloneSolution() {
ProductionConsumptionBalancing clone = new ProductionConsumptionBalancing();
// Transfer consumption and production values
clone.totalElectricityConsumption = this.totalElectricityConsumption;
clone.totalElectricityProduction = this.totalElectricityProduction;
// Shallow copy offer lists (shouldn't change)
clone.offers = this.offers;
// Shallow copy of dummy list
clone.dummies = this.dummies;
// Deep copy schedule
...
Starting from 6.0.0.Beta1, OptaPlanner (= Drools Planner) supports automatic cloning out-of-the-box. So you don't need to implement the cloneSolution() method no more, because planner figures it out automatically. Because you don't need to implement the method no more, you can't implement it incorrectly.
Note that you can still implement a custom clone method if you really want too.

How to assign/opt from multiple delegates for a 'moled' method?

I am currently examining Moles from the outside while I wait for my VS 2010 license, and I wonder whether Moles allows me to:
provide the ability to assígn multiple mole delegates for a method being moled, perhaps at a test fixture setup level?
switch in runtime in my test case, which of my mole delegates must be invoked for the upcoming call(s) to the moled method being isolated?
Any hints?
Best Answer:
It is much easier and makes far more sense to include gating logic in the detour method, than using two stubs for the same method! For example, MyMethod reads data from three different files on disk, each requiring different mock data to be returned. We may detour System.IO.File.OpenRead and gate the return value by analyzing the input parameters of OpenRead:
TEST METHOD:
[TestMethod]
[HostType("Moles")]
public void Test()
{
System.IO.Moles.MFile.OpenReadString = filePath => {
var mockStream = new System.IO.FileStream();
byte[] buffer;
switch (filePath)
{
case #"C:\DataFile.dat":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
case #"C:\TextFile.txt":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
case #"C:\LogFile.log":
mockStream.Write(buffer, 0, 0); // Populate stream
break;
}
return mockStream;
};
var target = new MyClass();
target.MyMethod();
}
TARGET TYPE:
using System.IO;
public class MyClass
{
public void MyMethod()
{
var fileAData = File.OpenRead(#"C:\DataFile.dat");
var fileBData = File.OpenRead(#"C:\TextFile.txt");
var fileCData = File.OpenRead(#"C:\LogFile.log");
}
}
Direct Answer to Your Questions:
Yes to #1: instantiate one type for each detour, and then use each for the desired behavior. And, yes to #2: act upon one instance of the mole type or the other. This requires addition of method input parameters or class constructor injection.
For example, MyMethod reads three data files from disk, and you need to pass back three different data mocks. MyMethod requires three parameters, an overtly intrusive solution. (Note input parameters are FileInfo type; because, System.IO>File is static and can not be instantiated: For example:
TEST METHOD:
[TestMethod]
[HostType("Moles")]
public void Test()
{
var fileInfoMoleA = new System.IO.Moles.MFileInfo();
fileInfoMoleA.OpenRead = () => { return new FileStream(); };
var fileInfoMoleB = new System.IO.Moles.MFileInfo();
fileInfoMoleB.OpenRead = () => { return new FileStream(); };
var fileInfoMoleC = new System.IO.Moles.MFileInfo();
fileInfoMoleC.OpenRead = () => { return new FileStream(); };
var target = new MyClass();
target.MyMethod(fileInfoMoleA, fileInfoMoleB, fileInfoMoleC);
}
TARGET TYPE:
using System.IO;
public class MyClass
{
// Input parameters are FileInfo type; because, System.IO.File
// is a static class, and can not be instantiated.
public void MyMethod(FileInfo fileInfoA, FileInfo fileInfoB, FileInfo fileInfoC)
{
var fileAData = fileInfoA.OpenRead();
var fileBData = fileInfoB.OpenRead();
var fileCData = fileInfoC.OpenRead();
}
}
UPDATE:
In response to #Chai comment, it is possible to create common methods, within the test project, that may be referenced as the mole detour delegate. For example, you may wish to write a common method that may be referenced by any unit test, that sets up a variety of pre-configured scenarios. The following example displays how a parameterized method could be used. Get creative -- they're just method calls!
TARGET TYPES:
namespace PexMoleDemo
{
public class MyClass
{
private MyMath _math;
public MyClass()
{
_math = new MyMath() { left = 1m, right = 2m };
}
public decimal GetResults()
{
return _math.Divide();
}
}
public class MyOtherClass
{
private MyMath _math;
public MyOtherClass()
{
_math = new MyMath() { left = 100m, right = 200m };
}
public decimal Divide()
{
return _math.Divide();
}
}
public class MyMath
{
public decimal left { get; set; }
public decimal right { get; set; }
public decimal Divide()
{
return left / right;
}
}
}
TEST METHODS:
ArrangeScenarios() sets up mole detours, by switching on the enumeration parameter. This allows the same scenarios to be erected, in a DRY manner, throughout many tests.
using System;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PexMoleDemo;
[assembly: MoledAssembly("PexMoleDemo")]
namespace TestProject1
{
[TestClass()]
public class ProgramTest
{
public enum Scenarios
{
DivideByZero,
MultiplyInsteadOfDivide
}
private void ArrangeScenario(Scenarios scenario)
{
switch (scenario)
{
case Scenarios.DivideByZero:
PexMoleDemo.Moles.MMyMath.AllInstances.rightGet =
instance => { return 0m; };
break;
case Scenarios.MultiplyInsteadOfDivide:
PexMoleDemo.Moles.MMyMath.AllInstances.Divide =
instance => { return instance.left * instance.right; };
break;
default:
throw new NotImplementedException("Invalid scenario.");
}
}
[TestMethod]
[HostType("Moles")]
[ExpectedException(typeof(DivideByZeroException))]
public void Test1()
{
ArrangeScenario(Scenarios.DivideByZero);
var target = new PexMoleDemo.MyClass();
var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
var left = math.left;
var right = math.right;
var actual = target.GetResults();
}
[TestMethod]
[HostType("Moles")]
public void Test2()
{
ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
// Perform some sort of test that determines if code breaks
// when values are multiplied instead of divided.
}
[TestMethod]
[HostType("Moles")]
[ExpectedException(typeof(DivideByZeroException))]
public void Test3()
{
ArrangeScenario(Scenarios.DivideByZero);
var target = new PexMoleDemo.MyOtherClass();
var math = new PexMoleDemo.MyMath() { left = 1, right = 2 };
var left = math.left;
var right = math.right;
var actual = target.Divide();
}
[TestMethod]
[HostType("Moles")]
public void Test4()
{
ArrangeScenario(Scenarios.MultiplyInsteadOfDivide);
// Perform some sort of test that determines if code breaks
// when values are multiplied instead of divided.
}
}
}