I am attempting to write a parameterized test for an interface Foo, which declares a method getFooEventInt(int, int). I have written a paramterized test that works for a single instance of Foo (a FooImpl object).
public class FooTest {
#ParameterizedTest
#MethodSource("getFooEvenIntProvider")
public void getFooEvenIntTest(int seed, int expectedResult) {
Foo foo = new FooImpl();
Assertions.assertEquals(expectedResult, foo.getFooEvenInt(seed));
}
private static Stream getFooEvenIntProvider() {
return Stream.of(
Arguments.of(-2, 0),
Arguments.of(-1, 0),
Arguments.of( 0, 2),
Arguments.of( 1, 2),
);
}
}
However, I'd like to be able to have getFooEvenIntTest(int, int) be invoked against a provided list of Foo implementation instances, with each iteration then using the provide list of seed/expectedResult values.
I realize I could do this as...
public class FooTest {
#ParameterizedTest
#MethodSource("getFooProvider")
public void getFooImplEvenIntTest(Foo foo) {
int[] expectedResult = { 0, 0, 2, 2 };
int[] seed = { -2, -1, 0, 1 };
for(int i=0; i<seed.length; i++) {
Assertions.assertEquals(expectedResult[i],
foo.getFooEvenInt(seed[i]));
}
}
private static Stream getFooProvider() {
return Stream.of(
Arguments.of(new FooImpl()),
Arguments.of(new FooImpl2())
);
}
}
Any ideas? I'll post if I figure it out, but I thought I'd check to see if this is even doable, or if there's a different approach.
I guess you think of combining two arguments streams. You could achieve this by creating the cartesian product of two arguments lists.
I have implemented that on https://github.com/joerg-pfruender/junit-goodies/blob/master/src/main/java/com/github/joergpfruender/junitgoodies/ParameterizedTestHelper.java
public static Stream<Arguments> cartesian(Stream a, Stream b) {
List argumentsA = (List) a.collect(Collectors.toList());
List argumentsB = (List) b.collect(Collectors.toList());
List<Arguments> result = new ArrayList();
for (Object o : argumentsA) {
Object[] objects = asArray(o);
for (Object o1 : argumentsB) {
Object[] objects1 = asArray(o1);
Object[] arguments = ArrayUtils.addAll(objects, objects1);
result.add(Arguments.of(arguments));
}
}
return result.stream();
}
private static Object[] asArray(Object o) {
Object[] objects;
if (o instanceof Arguments) {
objects = ((Arguments) o).get();
} else {
objects = new Object[]{o};
}
return objects;
}
Then your test code will be:
public static Stream<Arguments> fooIntsAndFooProvider() {
return ParameterizedTestHelper.cartesian(getFooEvenIntProvider(), getFooProvider());
}
#ParameterizedTest
#MethodSource("fooIntsAndFooProvider")
public void getFooImplEvenIntTest(Integer seed, Integer expectedResult, Foo foo) {
Assertions.assertEquals(expectedResult,
foo.getFooEvenInt(seed));
}
BLUF: I will interpret the crickets to mean "even if you could, you shouldn't be nesting parameterized tests", in which case I run with the approach outlined below.
For an interface Foo...
public interface Foo {
public char getFirstChar(String strValue);
public int getNextEvenInt(int seed);
}
The "best" use of parameterized tests for implementations of Foo would be...
public class FooTest {
#ParameterizedTest
#MethodSource("getFooProvider")
public void getFirstCharTest(Foo foo) {
char[] expectedResult = { 'a', 'b', 'c', 'd' };
String[] seed = { "alpha", "bravo", "charlie", "delta" };
for(int i=0; i<seed.length; i++) {
Assertions.assertEquals(expectedResult[i],
foo.getFirstChar(seed[i]));
}
}
#ParameterizedTest
#MethodSource("getFooProvider")
public void getNextEvenIntTest(Foo foo) {
int[] expectedResult = { 0, 0, 2, 2 };
int[] seed = { -2, -1, 0, 1 };
for(int i=0; i<seed.length; i++) {
Assertions.assertEquals(expectedResult[i],
foo.getFooEvenInt(seed[i]));
}
}
private static Stream getFooProvider() {
return Stream.of(
Arguments.of(new FooImplOne()),
Arguments.of(new FooImplTwo())
// extend as need for implementations of Foo
);
}
}
While I won't get the "warm fuzzies" of seeing the passing results for each value-pair in the various tests, it will fulfill my goal of having a test at the interface level that I can easily extend to validate/verify the interface's implementations.
Related
In Dart, when I create a new instance of an object, it seems that it is in fact the original object and not a new, separate copy. Consider this code:
class Bar{
String name;
Bar(this.name);
}
class Foo{
String name;
List<Bar>bars;
Foo({required this.name, required this.bars});
}
extension ExtendFoo on Foo{
void addBar(String barName){
this.bars.add(Bar(barName));
}
}
class Manage{
final List<Foo> _fooList =
[
Foo(name : 'foo1', bars: [Bar('bar1'),Bar('bar2')]),
Foo(name : 'foo2', bars: [Bar('bar21'),Bar('bar22')]),
Foo(name : 'foo3', bars: [Bar('bar31'),Bar('bar32')]),
];
List<Foo> get fooList => _fooList;
Foo getFoo(String fooName){
return _fooList.firstWhere((foo)=> foo.name == fooName);
}
}
void main() {
Manage manage = Manage();
Foo editFoo = manage.getFoo('foo2');
editFoo.addBar('newBar');
editFoo.name = 'newName';
}
The objects editFoo and manage[1] are 100% equal at the end of this. In other words: when I updated editFoo I was also updating manage[1].
I actually want a copy of manage[1] that I can manipulate and update without also updating manage[1]. Then later I may decide to replace manage[1] with the copy, but I want control over if and when that happens.
This is because return _fooList.firstWhere((foo)=> foo.name == fooName); is not creating a new object of Foo. It is passing the Foo instance by reference.
Take a look at this
class Bar {
String name;
Bar(this.name);
}
class Foo {
String name;
List<Bar> bars;
Foo({required this.name, required this.bars});
}
extension ExtendFoo on Foo {
void addBar(String barName) {
this.bars.add(Bar(barName));
}
}
class Manage {
final List<Foo> _fooList = [
Foo(name: 'foo1', bars: [Bar('bar1'), Bar('bar2')]),
Foo(name: 'foo2', bars: [Bar('bar21'), Bar('bar22')]),
Foo(name: 'foo3', bars: [Bar('bar31'), Bar('bar32')]),
];
List<Foo> get fooList => _fooList;
Foo getFoo(String fooName) {
int i = _fooList.indexWhere((foo) => foo.name == fooName);
if (i == -1) {
return null;
}
Foo foo = _fooList[i];
Foo? getFoo(String fooName) {
int i = _fooList.indexWhere((foo) => foo.name == fooName);
if (i == -1) {
return null;
}
Foo foo = _fooList[i];
return Foo(name: foo.name, bars: List.generate(foo.bars.length, (i) => foo.bars[i]));
} }
}
void main() {
Manage manage = Manage();
Foo editFoo = manage.getFoo('foo2');
editFoo.addBar('newBar');
editFoo.name = 'newName';
print(editFoo.name); //newName
print(manage.fooList[1].name); //foo2
print(manage.fooList[1] == editFoo); //false
}
If you have null safety on use this:
Foo? getFoo(String fooName) {
int i = _fooList.indexWhere((foo) => foo.name == fooName);
if (i == -1) {
return null;
}
Foo foo = _fooList[i];
return Foo(name: foo.name, bars: List.generate(foo.bars.length, (i) => foo.bars[i]));
}
And this:
Foo editFoo = manage.getFoo('foo2')!;
Let say we have an object:
#:checkDirty
class Test {
var a:Int;
var b(default, default):String;
var c(get, set):Array<Int>;
public function new() {
...
}
public function get_c() {
...
}
public function set_c(n) {
...
}
}
Could we write a macro checkDirty so that any change to field/properties would set property dirty to true. Macro would generate dirty field as Bool and clearDirty function to set it to false.
var test = new Test();
trace(test.dirty); // false
test.a = 12;
trace(test.dirty); // true
test.clearDirty();
trace(test.dirty); //false
test.b = "test"
trace(test.dirty); //true
test.clearDirty();
test.c = [1,2,3];
trace(test.dirty); //true
Just to note - whenever you consider proxying access to an object, in my experience, there are always hidden costs / added complexity. :)
That said, you have a few approaches:
First, if you want it to be pure Haxe, then either a macro or an abstract can get the job done. Either way, you're effectively transforming every property access into a function call that sets the value and also sets dirty.
For example, an abstract using the #:resolve getter and setter can be found in the NME source code, replicated here for convenience:
#:forward(decode,toString)
abstract URLVariables(URLVariablesBase)
{
public function new(?inEncoded:String)
{
this = new URLVariablesBase(inEncoded);
}
#:resolve
public function set(name:String, value:String) : String
{
return this.set(name,value);
}
#:resolve
public function get(name:String):String
{
return this.get(name);
}
}
This may be an older syntax, I'm not sure... also look at the operator overloading examples on the Haxe manual:
#:op(a.b) public function fieldRead(name:String)
return this.indexOf(name);
#:op(a.b) public function fieldWrite(name:String, value:String)
return this.split(name).join(value);
Second, I'd just point out that if the underlying language / runtime supports some kind of Proxy object (e.g. JavaScript Proxy), and macro / abstract isn't working as expected, then you could build your functionality on top of that.
I wrote a post (archive) about doing this kind of thing (except for emitting events) before - you can use a #:build macro to modify class members, be it appending an extra assignment into setter or replacing the field with a property.
So a modified version might look like so:
class Macro {
public static macro function build():Array<Field> {
var fields = Context.getBuildFields();
for (field in fields.copy()) { // (copy fields so that we don't go over freshly added ones)
switch (field.kind) {
case FVar(fieldType, fieldExpr), FProp("default", "default", fieldType, fieldExpr):
var fieldName = field.name;
if (fieldName == "dirty") continue;
var setterName = "set_" + fieldName;
var tmp_class = macro class {
public var $fieldName(default, set):$fieldType = $fieldExpr;
public function $setterName(v:$fieldType):$fieldType {
$i{fieldName} = v;
this.dirty = true;
return v;
}
};
for (mcf in tmp_class.fields) fields.push(mcf);
fields.remove(field);
case FProp(_, "set", t, e):
var setter = Lambda.find(fields, (f) -> f.name == "set_" + field.name);
if (setter == null) continue;
switch (setter.kind) {
case FFun(f):
f.expr = macro { dirty = true; ${f.expr}; };
default:
}
default:
}
}
if (Lambda.find(fields, (f) -> f.name == "dirty") == null) fields.push((macro class {
public var dirty:Bool = false;
}).fields[0]);
return fields;
}
}
which, if used as
#:build(Macro.build())
#:keep class Some {
public function new() {}
public var one:Int;
public var two(default, set):String;
function set_two(v:String):String {
two = v;
return v;
}
}
Would emit the following JS:
var Some = function() {
this.dirty = false;
};
Some.prototype = {
set_two: function(v) {
this.dirty = true;
this.two = v;
return v;
}
,set_one: function(v) {
this.one = v;
this.dirty = true;
return v;
}
};
I need to know, what would be proper way to implement Maps with 64 bit keys. There will not be so many items in them, I just need to use various bits of the key for various things with large enough address space and I need it to be very fast, so String keys would probably be too slow. So far I tried:
import haxe.Int64;
import haxe.Unserializer;
import haxe.Serializer;
class Test {
static function main () {
var key:Int64 = 1 << 63 | 0x00000001;
var omap:Map<Int64, String> = new Map<Int64, String>();
omap.set(key, "test");
var smap:Map<Int64, String> = Unserializer.run(Serializer.run(omap));
var key2:Int64 = 1 << 63 | 0x00000001;
trace(key+" "+smap.get(key2));
}
}
http://try.haxe.org/#7CDb2
which obviously doesn't work, because haxe.Int64 creates an object instance. Using cpp.Int64 works, because it for some reason falls back to 32 bit integer in my cpp code and I don't know what am I doing wrong. How can I force it to "stay" 64 bit, or should I do it some other way?
EDIT: This is currently not working on native targets due to bug / current implementation in hxcpp: https://github.com/HaxeFoundation/hxcpp/issues/523
I figured out this workaround / wrapper, which may not be the most efficient solution possible, but it seems to work.
import haxe.Int64;
import haxe.Unserializer;
import haxe.Serializer;
class Test {
static function main () {
var key:Int64 = Int64.make(1000,1);
var omap:Int64Map<String> = new Int64Map();
omap.set(key, "test");
var smap:Int64Map<String> = Unserializer.run(Serializer.run(omap));
var key2:Int64 = Int64.make(1000,1);
trace(key+" "+smap.get(key2));
}
}
class Int64Map<V> {
private var map:Map<Int64,V>;
public function new() : Void {
this.map = new Map<Int64,V>();
}
public function set(key:Int64, value:V):Void {
this.map.set(key, value);
}
public inline function get(key:Int64):Null<V> {
var skey:Null<Int64> = getMapKey(key);
if (skey != null) return this.map.get(skey);
return null;
}
public inline function exists(key:Int64):Bool {
return (getMapKey(key) != null);
}
public function remove( key : Int64 ) : Bool {
var skey:Null<Int64> = getMapKey(key);
if (skey != null) return this.map.remove(skey);
return false;
}
public function keys() : Iterator<Int64> {
return this.map.keys();
}
public function toString() : String {
return this.map.toString();
}
public function iterator() : Iterator<V> {
return this.map.iterator();
}
private function getMapKey(key:Int64):Null<Int64> {
for (ikey in this.map.keys()){
if (Int64.eq(key, ikey)){
return ikey;
}
}
return null;
}
}
http://try.haxe.org/#57686
If I have a method such as this:
void someMethod(int one, int two, int three)
{
log.debug("One = ${one}, two = ${two}, three = ${three}")
}
Is there a way to avoid listing each param in the debit message? I want to print out values for all the parameters without necessarily listing each one separately.
You can just use varargs:
void someMethod( int... args ) {
println "Args = $args"
}
Worried about more than 3 arguments getting used while calling method? Then make sure you only deal with args[0] till args[2] inside the method.
You may also use interceptor construct:
class Sample {
void someMethod(int one, int two, int three) {
// println("One = ${one}, two = ${two}, three = ${three}")
}
}
class SampleInterceptor implements Interceptor {
boolean doInvoke() {
true
}
Object beforeInvoke(Object obj, String name, Object[] args) {
if(name == "someMethod")
println args
}
Object afterInvoke(Object obj, String name, Object[] args, Object result) {
result
}
}
def proxy = ProxyMetaClass.getInstance(Sample)
def interceptor = new SampleInterceptor()
proxy.interceptor = interceptor
proxy.use {
def h = new Sample()
h.someMethod(1,2,3)
}
Have a look at the sample.
I am trying to get multithreading more unraveled in my head. I made these three classes.
A global variable class
public partial class globes
{
public bool[] sets = new bool[] { false, false, false };
public bool boolChanged = false;
public string tmpStr = string.Empty;
public int gcount = 0;
public bool intChanged = false;
public Random r = new Random();
public bool gDone = false;
public bool first = true;
}
Drop in point
class Driver
{
static void Main(string[] args)
{
Console.WriteLine("start");
globes g = new globes();
Thread[] threads = new Thread[6];
ParameterizedThreadStart[] pts = new ParameterizedThreadStart[6];
lockMe _lockme = new lockMe();
for (int b = 0; b < 3; b++)
{
pts[b] = new ParameterizedThreadStart(_lockme.paramThreadStarter);
threads[b] = new Thread(pts[b]);
threads[b].Name = string.Format("{0}", b);
threads[b].Start(b);
}
}
}
And then my threading class
class lockMe
{
#region Fields
private string[] words = new string[] {"string0", "string1", "string2", "string3"};
private globes g = new globes();
private object myKey = new object();
private string[] name = new string[] { String.Empty, String.Empty, String.Empty };
#endregion
#region methods
// first called for all threads
private void setName(Int16 i)
{
Monitor.Enter(myKey);
{
try
{
name[i] = string.Format("{0}:{1}", Thread.CurrentThread.Name, g.r.Next(100, 500).ToString());
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// thread 1
private void changeBool(Int16 a)
{
Monitor.Enter(myKey);
{
try
{
int i = getBools();
//Thread.Sleep(3000);
if (g.gcount > 5) { g.gDone = true; return; }
if (i == 3) resets();
else { for (int x = 0; x <= i; i++) { g.sets[x] = true; } }
Console.WriteLine("Thread {0} ran through changeBool()\n", name[a]);
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// thread 2
private void changeInt(Int16 i)
{
Monitor.Enter(myKey);
{
try
{
g.gcount++;
//Thread.Sleep(g.r.Next(1000, 3000));
Console.WriteLine("Thread {0}: Count is now at {1}\n", name[i], g.gcount);
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// thread 3
private void printString(Int16 i)
{
Monitor.Enter(myKey);
{
try
{
Console.WriteLine("...incoming...");
//Thread.Sleep(g.r.Next(1500, 2500));
Console.WriteLine("Thread {0} printing...{1}\n", name[i], words[g.r.Next(0, 3)]);
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// not locked- called from within a locked peice
private int getBools()
{
if ((g.sets[0] == false) && (g.sets[1] == false) && (g.sets[2] == false)) return 0;
else if ((g.sets[0] == true) && (g.sets[1] == false) && (g.sets[2] == false)) return 1;
else if ((g.sets[2] == true) && (g.sets[3] == false)) return 2;
else if ((g.sets[0] == true) && (g.sets[1] == true) && (g.sets[2] == true)) return 3;
else return 99;
}
// should not need locks- called within locked statement
private void resets()
{
if (g.first) { Console.WriteLine("FIRST!!"); g.first = false; }
else Console.WriteLine("Cycle has reset...");
}
private bool getStatus()
{
bool x = false;
Monitor.Enter(myKey);
{
try
{
x = g.gDone;
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
return x;
}
#endregion
#region Constructors
public void paramThreadStarter(object starter)
{
Int16 i = Convert.ToInt16(starter);
setName(i);
do
{
switch (i)
{
default: throw new Exception();
case 0:
changeBool(i);
break;
case 1:
changeInt(i);
break;
case 2:
printString(i);
break;
}
} while (!getStatus());
Console.WriteLine("fin");
Console.ReadLine();
}
#endregion
}
So I have a few questions. The first- is it better to have my global class set like this? Or should I be using a static class with properties and altering them that way? Next question is, when this runs, at random one of the threads will run, pulse/exit the lock, and then step right back in (sometimes like 5-10 times before the next thread picks up the lock). Why does this happen?
Each thread is given a certain amount of CPU time, I doubt that one particular thread is getting more actual CPU time over the others if you are locking all the calls in the same fashion and the thread priorities are the same among the threads.
Regarding how you use your global class, it doesn't really matter. The way you are using it wouldn't change it one way or the other. Your use of globals was to test thread safety, so when multiple threads are trying to change shared properties all that matters is that you enforce thread safety.
Pulse might be a better option knowing that only one thread can actually enter, pulseAll is appropriate when you lock something because you have a task to do, once that task is complete and won't lock the very next time. In your scenario you lock every time so doing a pulseAll is just going to waste cpu because you know that it will be locked for the next request.
Common example of when to use static classes and why you must make them thread safe:
public static class StoreManager
{
private static Dictionary<string,DataStore> _cache = new Dictionary<string,DataStore>(StringComparer.OrdinalIgnoreCase);
private static object _syncRoot = new object();
public static DataStore Get(string storeName)
{
//this method will look for the cached DataStore, if it doesn't
//find it in cache it will load from DB.
//The thread safety issue scenario to imagine is, what if 2 or more requests for
//the same storename come in? You must make sure that only 1 thread goes to the
//the DB and all the rest wait...
//check to see if a DataStore for storeName is in the dictionary
if ( _cache.ContainsKey( storeName) == false )
{
//only threads requesting unknown DataStores enter here...
//now serialize access so only 1 thread at a time can do this...
lock(_syncRoot)
{
if (_cache.ContainsKey(storeName) == false )
{
//only 1 thread will ever create a DataStore for storeName
DataStore ds = DataStoreManager.Get(storeName); //some code here goes to DB and gets a DataStore
_cache.Add(storeName,ds);
}
}
}
return _cache[storeName];
}
}
What's really important to see is that the Get method only single threads the call when there is no DataStore for the storeName.
Double-Check-Lock:
You can see the first lock() happens after an if, so imagine 3 threads simultaneously run the if ( _cache.ContainsKey(storeName) .., now all 3 threads enter the if. Now we lock so that only 1 thread can enter, now we do the same exact if statement, only the very first thread that gets here will actually pass this if statement and get the DataStore. Once the first thread .Add's the DataStore and exits the lock the other 2 threads will fail the second check (double check).
From that point on any request for that storeName will get the cached instance.
So we single threaded our application only in the spots that required it.