How do I define Context for DataTables in specs2 - unit-testing

I'm trying to define some context so that it's executed for each row of data table (before assertion is run on each row).
I've found this example but for the life of me I can't figure out how to write the full test suite.
I'd like to define context once and share it with all examples.
Here is roughly what I have:
class SomeSuite extends Specification with DataTables {
// TODO: define context somehow???
// val context = new Before { println("BEFORE") }
"test 1" should {
"do something" in {
context |
"col1" | "col2" |
val1 ! val2 |
val3 ! val4 |> {
(a, b) => //some assertion with (a, b)
}
}
}
}
I'd like to see "BEFORE" printed each time (total 2 times) before each assertion with (a, b).
I would really appreciate any help.
Thanks ;)
Thanks to Eric here is my final code. I only added 'implicit' since context is shared for many tests:
class SomeSuite extends Specification with DataTables {
implicit val context = new Before { def before = println("BEFORE") }
"test 1" should {
"do something" in {
"col1" | "col2" |
val1 ! val2 |
val3 ! val4 |> { (a, b) =>
a must_== b // this is wrapped with context
}
}
}
}

The easy way is to use the apply method of a Context
class SomeSuite extends Specification with DataTables {
val context = new Before { def before = println("BEFORE") }
"test 1" should {
"do something" in {
"col1" | "col2" |
val1 ! val2 |
val3 ! val4 |> { (a, b) =>
context { a must_== b }
}
}
}
}

Related

Get rid of nested for loops with std::ranges

Let I have a code:
for (auto& a : x.as)
{
for (auto& b : a.bs)
{
for (auto& c : b.cs)
{
for (auto& d : c.ds)
{
if (d.e == ..)
{
return ...
}
}
}
}
}
as, bs, cs, ds - std::vector of corresponding elements.
Is it possible with std::ranges to convert four ugly loops into a beatifull one line expression?
With join and transform views, you might do:
for (auto& e : x.as | std::views::transform(&A::bs) | std::views::join
| std::views::transform(&B::cs) | std::views::join
| std::views::transform(&C::ds) | std::views::join
| std::views::transform(&D::e))
{
// ...
}
Demo

ANTLR - How to extact units from a dimension

I'm using ANTLR4 and the CSS grammar from https://github.com/antlr/grammars-v4/tree/master/css3. The grammar defines the following ( pared down a little for brevity )
dimension
: ( Plus | Minus )? Dimension
;
fragment FontRelative
: Number E M
| Number E X
| Number C H
| Number R E M
;
fragment AbsLength
: Number P X
| Number C M
| Number M M
| Number I N
| Number P T
| Number P C
| Number Q
;
fragment Angle
: Number D E G
| Number R A D
| Number G R A D
| Number T U R N
;
fragment Length
: AbsLength
| FontRelative
;
Dimension
: Length
| Angle
;
The matching works fine but I don't see an obvious way to extract the units. The parser creates a DimensionContext which has 3 TerminalNode members - Dimension, Plus and Minus. I'd like to be able to extract the unit during parse without having to do additional string parsing.
I know that one issue that the Length and Angle are fragments. I changed the grammar not use fragments
Unit
: 'em'
| 'ex'
| 'ch'
| 'rem'
| 'vw'
| 'vh'
| 'vmin'
| 'vmax'
| 'px'
| 'cm'
| 'mm'
| 'in'
| 'pt'
| 'q'
| 'deg'
| 'rad'
| 'grad'
| 'turn'
| 'ms'
| 's'
| 'hz'
| 'khz'
;
Dimension : Number Unit;
And things still parse but I don't get any more context about what the units are - the Dimension is still a single TerminalNode. Is there a way to deal with this without having to pull apart the full token string?
You will want to do as little as possible in the lexer:
NUMBER
: Dash? Dot Digit+ { atNumber(); }
| Dash? Digit+ ( Dot Digit* )? { atNumber(); }
;
UNIT
: { aftNumber() }?
( 'px' | 'cm' | 'mm' | 'in'
| 'pt' | 'pc' | 'em' | 'ex'
| 'deg' | 'rad' | 'grad' | '%'
| 'ms' | 's' | 'hz' | 'khz'
)
;
The trick is to produce the NUMBER and UNIT as separate tokens, yet limited to the required ordering. The actions in the NUMBER rule just set a flag and the UNIT predicate ensures that a UNIT can only follow a NUMBER:
protected void atNumber() {
_number = true;
}
protected boolean aftNumber() {
if (_number && Character.isWhitespace(_input.LA(1))) return false;
if (!_number) return false;
_number = false;
return true;
}
The parser rule is trivial, but preserves the detail required:
number
: NUMBER UNIT?
;
Use a tree-walk, parse the NUMBER to a Double and an enum (or equivalent) to provide the semantic UNIT characterization:
public enum Unit {
CM("cm", true, true), // 1cm = 96px/2.54
MM("mm", true, true),
IN("in", true, true), // 1in = 2.54cm = 96px
PX("px", true, true), // 1px = 1/96th
PT("pt", true, true), // 1pt = 1/72th
EM("em", false, true), // element font size
REM("rem", false, true), // root element font size
EX("ex", true, true), // element font x-height
CAP("cap", true, true), // element font nominal capital letters height
PER("%", false, true),
DEG("deg", true, false),
RAD("rad", true, false),
GRAD("grad", true, false),
MS("ms", true, false),
S("s", true, false),
HZ("hz", true, false),
KHZ("khz", true, false),
NONE(Strings.EMPTY, true, false), // 'no unit specified'
INVALID(Strings.UNKNOWN, true, false);
public final String symbol;
public final boolean abs;
public final boolean len;
private Unit(String symbol, boolean abs, boolean len) {
this.symbol = symbol;
this.abs = abs;
this.len = len;
}
public boolean isAbsolute() { return abs; }
public boolean isLengthUnit() { return len; }
// call from the visitor to resolve from `UNIT` to Unit
public static Unit find(TerminalNode node) {
if (node == null) return NONE;
for (Unit unit : values()) {
if (unit.symbol.equalsIgnoreCase(node.getText())) return unit;
}
return INVALID;
}
#Override
public String toString() {
return symbol;
}
}

Recursive Proc in Crystal

Is recursive proc posible in Crystal?
Something like lambda in Ruby
I'm trying to do a y-combinator in Crystal,something like Ruby one:
puts -> {
fact_improver = ->(partial) {
-> (n) { n.zero? ? 1 : n * partial.(n-1) }
}
y = ->(f) {
->(x) { f.(->(v) { x.(x).(v) }) }.(
->(x) { f.(->(v) { x.(x).(v) }) }
)
}
fact = y.(fact_improver)
fact = fact_improver.(fact)
fact.(100)
}.()
The above code was taken from Y Not- Adventures in Functional Programming
As far as I know Crystal does not have recursive procs. But to create Y combinator you don't need a recursive proc. Actually, according to the definition:
In functional programming, the Y combinator can be used to formally define recursive functions in a programming language that doesn't support recursion.
Here is an example of Y combinator written in Crystal using recursive types:
alias T = Int32
alias Func = T -> T
alias FuncFunc = Func -> Func
alias RecursiveFunction = RecursiveFunction -> Func
fact_improver = ->(partial : Func) {
->(n : T) { n.zero? ? 1 : n * partial.call(n - 1) }
}
y = ->(f : FuncFunc) {
g = ->(r : RecursiveFunction) { f.call(->(x : T) { r.call(r).call(x) }) }
g.call(g)
}
fact = y.call(fact_improver)
fact = fact_improver.call(fact)
fact.call(5) # => 120
UPDATE: it is possible to create recursive proc in Crystal with uninitialized keyword:
g = uninitialized Int32 -> Int32
g = ->(n : Int32) { n.zero? ? 1 : n * g.call(n - 1) }
g.call(5) # => 120
Thanks to #mgarciaisaia for the comment.

Make a new list from two other lists of different types by comparing values of each type

I have two Lists of objects that both implement an interface, but are otherwise unrelated. How can I create a new collection of objects containing only the objects of one of the lists that match a value in the other list?
Obviously I could use a for loop & do this manually, but I'd like to know how I can do this using Kotlin's standard library collection filtering functions.
So here's an example:
interface Ids
{
val id: Int
}
data class A(override val id: Int, val name: String) : Ids
data class B(override val id: Int, val timestamp: Long) : Ids
fun main(args: Array<String>) {
val a1 = A(1, "Steve")
val a2 = A(2, "Ed")
val aCol = listOf(a1, a2)
val b2 = B(2, 12345)
val b3 = B(3, 67890)
val bCol = listOf(b2, b3)
val matches = mutableListOf<B>()
// This is where I'm stuck.
// I want to filter bCol using objects from aCol as a filter.
// The result should be that matches contains only a single object: b2
// because bCol[0].id == aCol[1].id
// I'm guessing I need to start with something like this:
bCol.filterTo(matches) { ??? }
}
A straightforward approach would be to search aCol for an object with the same id for each b in bCol:
bCol.filter { b -> aCol.any { a -> a.id == b.id } }
However that may become too slow if your lists are big enough.
To make it more scalable you can first build a set of all ids in aCol:
val aColIds = aCol.map { it.id }.toSet()
And then use Set.contains method to determine whether b.id is in aColIds:
bCol.filter { it.id in aColIds }
// or equivalent
bCol.filter { aColIds.contains(it.id) }

Returning list in ANTLR for type checking, language java

I am working on ANLTR to support type checking. I am in trouble at some point. I will try to explain it with an example grammar, suppose that I have the following:
#members {
private java.util.HashMap<String, String> mapping = new java.util.HashMap<String, String>();
}
var_dec
: type_specifiers d=dec_list? SEMICOLON
{
mapping.put($d.ids.get(0).toString(), $type_specifiers.type_name);
System.out.println("identext = " + $d.ids.get(0).toString() + " - " + $type_specifiers.type_name);
};
type_specifiers returns [String type_name]
: 'int' { $type_name = "int";}
| 'float' {$type_name = "float"; }
;
dec_list returns [List ids]
: ( a += ID brackets*) (COMMA ( a += ID brackets* ) )*
{$ids = $a;}
;
brackets : LBRACKET (ICONST | ID) RBRACKET;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
LBRACKET : '[';
RBRACKET : ']';
In rule dec_list, you will see that I am returning List with ids. However, in var_dec when I try to put the first element of the list (I am using only get(0) just to see the return value from dec_list rule, I can iterate it later, that's not my point) into mapping I get a whole string like
[#4,6:6='a',<17>,1:6]
for an input
int a, b;
What I am trying to do is to get text of each ID, in this case a and b in the list of index 0 and 1, respectively.
Does anyone have any idea?
The += operator creates a List of Tokens, not just the text these Tokens match. You'll need to initialize the List in the #init{...} block of the rule and add the inner-text of the tokens yourself.
Also, you don't need to do this:
type_specifiers returns [String type_name]
: 'int' { $type_name = "int";}
| ...
;
simply access type_specifiers's text attribute from the rule you use it in and remove the returns statement, like this:
var_dec
: t=type_specifiers ... {System.out.println($t.text);}
;
type_specifiers
: 'int'
| ...
;
Try something like this:
grammar T;
var_dec
: type dec_list? ';'
{
System.out.println("type = " + $type.text);
System.out.println("ids = " + $dec_list.ids);
}
;
type
: Int
| Float
;
dec_list returns [List ids]
#init{$ids = new ArrayList();}
: a=ID {$ids.add($a.text);} (',' b=ID {$ids.add($b.text);})*
;
Int : 'int';
Float : 'float';
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
Space : ' ' {skip();};
which will print the following to the console:
type = int
ids = [a, b, foo]
If you run the following class:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
TLexer lexer = new TLexer(new ANTLRStringStream("int a, b, foo;"));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.var_dec();
}
}