Skip to content

Commit

Permalink
Merge pull request #17 from LisiLisenok/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
LisiLisenok authored Mar 27, 2017
2 parents ca7adfb + 0adae15 commit 559fe1c
Show file tree
Hide file tree
Showing 146 changed files with 5,529 additions and 1,171 deletions.
2 changes: 0 additions & 2 deletions .ceylon/.gitignore

This file was deleted.

2 changes: 0 additions & 2 deletions .ceylon/config
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@ source=examples
[defaults]
encoding=UTF-8

[formattool]
profile=my
4 changes: 1 addition & 3 deletions .ceylon/config~
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@ source=examples

[defaults]
encoding=UTF-8

[formattool]
profile=my

31 changes: 19 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,46 @@ is an extension to SDK `ceylon.test` module with following capabilities:
* multi-reporting: several failures or successes can be reported for a one particular test execution (test function),
each report is represented as test variant and might be marked with `String` title
* reporting test results using charts (or plots)
* benchmarks

The module is available on [Ceylon Herd](https://herd.ceylon-lang.org/modules/herd.asynctest).
Current version is 0.6.0.
Current version is 0.7.0.


#### Project structure

master branch contains the latest release
develop branch contains the currently developed version


#### Ceylon compiler / platform

Compiled with Ceylon 1.3.1
Compiled with Ceylon 1.3.2
Available on JVM only


#### Dependencies

* ceylon.collection/1.3.1
* ceylon.file/1.3.1 shared
* ceylon.language/1.3.1
* ceylon.test/1.3.1 shared
* java.base/8 JDK
* ceylon.collection/1.3.2
* ceylon.file/1.3.2 shared
* ceylon.language/1.3.2
* ceylon.test/1.3.2 shared
* java.base/8 JDK
* java.management/8 JDK


#### Usage and documentation

The extension is aimed to be run using Ceylon test tool.
See usage details in [API documentation](https://modules.ceylon-lang.org/repo/1/herd/asynctest/0.6.0/module-doc/api/index.html).
See usage details in [API documentation](https://modules.ceylon-lang.org/repo/1/herd/asynctest/0.7.0/module-doc/api/index.html).


#### Examples

* Test of [Fibonacci numbers calculation](examples/herd/examples/asynctest/fibonacci).
Calculation function is executed on separated thread and returns results using `ceylon.promise`.
* [Time scheduler](examples/herd/examples/asynctest/scheduler) testing.
* [Microbenchmark](examples/herd/examples/asynctest/mapperformance) -
comparative performance test of Ceylon / Java HashMap and TreeMap.
* [Time scheduler](examples/herd/examples/asynctest/scheduler) testing.
* [Benchmarking](examples/herd/examples/asynctest/benchmark) examples of benchmarks.
* [Matchers](examples/herd/examples/asynctest/matchers) - matchers usage.
* [Generics](examples/herd/examples/asynctest/generics) - type-parameterized testing.
* [Parameterized](examples/herd/examples/asynctest/parameterized) - type- and value- parameterized testing.
* [Rules](examples/herd/examples/asynctest/rule) - test rules usage.
45 changes: 45 additions & 0 deletions examples/herd/examples/asynctest/benchmark/LockFreeQueue.ceylon
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import java.util.concurrent.atomic {
AtomicReference
}


"Lock free queue."
shared class LockFreeQueue<Item>() given Item satisfies Object {

class Node (
shared variable Item? item = null,
Node? nextNode = null
) {
shared AtomicReference<Node?> next = AtomicReference<Node?>( nextNode );
}


AtomicReference<Node> head = AtomicReference<Node>( Node() );
AtomicReference<Node> tail = AtomicReference<Node>( head.get() );

shared void enqueue( Item item ) {
Node newTail = Node( item );
variable Node oldTail = tail.get();
while ( !oldTail.next.compareAndSet( null, newTail ) ) {
oldTail = tail.get();
}
// adjust tail
tail.compareAndSet( oldTail, newTail );
}

shared Item? dequeue() {
// current head
variable Node oldHead = head.get();
// store next in order to retriev correct item even if next will be replaced
variable Node? next = oldHead.next.get();
// shift head to the next
while ( next exists, !head.compareAndSet( oldHead, next ) ) {
oldHead = head.get();
next = oldHead.next.get();
}
return next?.item;
}

shared Boolean empty => !head.get().next.get() exists;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import ceylon.test {

test
}
import herd.asynctest {

async,
AsyncTestContext
}
import herd.asynctest.benchmark {

writeRelativeToFastest,
benchmark,
NumberOfLoops,
Options,
MultiBench,
TimeUnit,
CPUClock
}


"[[LockFreeQueue]] multithread producer-consumer benchmark."
shared test async void lockFreeQueueProducerConsumer(AsyncTestContext context) {
// queue to test
LockFreeQueue<Integer> queue = LockFreeQueue<Integer>();
for ( i in 0 : 100 ) { queue.enqueue( 1 ); }

writeRelativeToFastest (
context,
benchmark (
Options(NumberOfLoops(500), NumberOfLoops(100), 100, TimeUnit.milliseconds, CPUClock),
[
MultiBench(
"producer-consumer",
() => queue.enqueue( 1 ),
queue.dequeue
)
],
[1, 1], [2, 1], [1, 2], [2, 2]
)
);
context.complete();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import herd.asynctest {
async,
AsyncTestContext
}
import herd.asynctest.benchmark {
NumberOfLoops,
benchmark,
Options,
RandomFlow,
SingleBench
}
import ceylon.test {
test
}
import herd.asynctest.match {
CloseTo
}


shared class RandomTestFunction() {


variable Integer f1Calls = 0;
variable Integer f2Calls = 0;
variable Integer f3Calls = 0;

void f1() => f1Calls ++;
void f2() => f2Calls ++;
void f3() => f3Calls ++;


shared async test void selectFunctionRandomly(AsyncTestContext context) {
benchmark (
Options(NumberOfLoops(1000), NumberOfLoops(100)),
[
SingleBench (
"random test function",
RandomFlow(1, [f1, 0.3], [f2, 0.2], [f3, 0.5])
)
]
);
Integer sum = f1Calls + f2Calls + f3Calls;
context.assertThat((f1Calls.float/sum*100+0.5).integer, CloseTo(30, 2), "first function % of calls", true);
context.assertThat((f2Calls.float/sum*100+0.5).integer, CloseTo(20, 2), "second function % of calls", true);
context.assertThat((f3Calls.float/sum*100+0.5).integer, CloseTo(50, 2), "third function % of calls", true);
context.complete();
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import herd.asynctest {
AsyncTestContext,
async
}
import ceylon.test {
test
}
import herd.asynctest.benchmark {
writeRelativeToFastest,
benchmark,
SingleBench,
Options,
NumberOfLoops
}


// benchmark parameters
Integer integerValue => 1;
Integer integerFunction() => 1;


"Benchmark function - narrow to `Integer` firstly."
Boolean isValue(Integer|Integer() source) {
if (is Integer source) {return true;}
else {return false;}
}

"Benchmark function - narrow to `Integer()` firstly."
Boolean isFunction(Integer|Integer() source) {
if (is Integer() source) {return true;}
else {return false;}
}


"What is faster narrowing to function of to class?:
Integer|Integer() source => ...
...
if (is Integer source) {return true; }
else {return false;}
or
if (is Integer() source) {return true; }
else {return false;}
"
shared test async void isValueOrFunction(AsyncTestContext context) {
writeRelativeToFastest (
context,
benchmark (
Options(NumberOfLoops(1000), NumberOfLoops(100)),
[
SingleBench("value", isValue),
SingleBench("function", isFunction)
],
[integerValue], [integerFunction]
)
);
context.complete();
}

Loading

0 comments on commit 559fe1c

Please sign in to comment.