Trying add scalacheck into the spray-testkit + specs2 example:
service with following route:
def myRoute = get(
path("add" / IntNumber / IntNumber) ((a, b) =>
complete((a+b).toString)
)
)
and the test spec for it:
"MyService" should {
"do calculation" in {
Get("/add/30/58") ~> myRoute ~> check {
responseAs[String] === "88"
}
}
"do calculation with scalacheck" in {
check { (a: Int, b: Int) ⇒
Get(s"/add/$a/$b") ~> myRoute ~> check {
responseAs[String] === s"${a+b}"
}
}
}
}
should be pretty simple, but my brain is not allowed to formulate the second test case. i get error like
...MyService.Spec.scala:44: not found: value a"
check { (a:Int, b:Int)
^
...MyService.Spec.scala:44: value ? is not a member of (Int, Int)
check { (a:Int, b:Int) ?
^
whats going on here and how to fix?
Replace the => for the arrow instead of the unicode character ⇒.
Then you should use prop instead of check and write:
"do calculation with scalacheck" in {
prop { (a: Int, b: Int) =>
Get(s"/add/$a/$b") ~> myRoute ~> check {
responseAs[String] === s"${a+b}"
}
}
}
Related
final_map = ["/7amd64-Aug2022.1":"2022-08-09","/7amd64-Oct2022.1":"2022-10-12","/7":"2022-11-08","/7amd64-Jul2022.1":"2022-07-12","/7amd64":"2022-11-08","/7amd64-June2022.1":"2022-06-14","/7amd64-beta":"2022-11-08","/7amd64-Sep2022.1":"2022-09-14","/7amd64-Nov2022.1":"2022-11-08","/_uploads":"2022-11-08"]
Jenkins Pipeline (below is the code I have, which is not working)
result = final_map.sort { a,b -> a.value <=> b.value }
echo "Output: ${result}"
Expecting to sort the map with date (value).
You can use a custom comparator for this. Check the following Groovy code.
final_map = ["/7amd64-Aug2022.1":"2022-08-09","/7amd64-Oct2022.1":"2022-10-12","/7":"2022-11-08","/7amd64-Jul2022.1":"2022-07-12","/7amd64":"2022-11-08","/7amd64-June2022.1":"2022-06-14","/7amd64-beta":"2022-11-08","/7amd64-Sep2022.1":"2022-09-14","/7amd64-Nov2022.1":"2022-11-08","/_uploads":"2022-11-08"]
final_map.sort { s1, s2 ->
def s1Date = new Date(s1.value.replace('-', '/'))
def s2Date = new Date(s2.value.replace('-', '/'))
if( s1Date.before(s2Date)) {
return -1
} else {
return 1
}
}
println final_map
I am trying to write a precondition to require a string to contain at least one non-whitespace character. I wrote the following:
predicate AllWhiteSpaceChars(s: string) {
forall i :: 0 <= i < |s| ==> s[i] in {' ', '\n', /*'\f',*/ '\r', '\t'/*, '\v'*/}
}
But I can't get my program to verify with it. The following fails:
method test1(s: string)
requires !AllWhiteSpaceChars(s)
{
print s;
}
method test2()
{
test1("./foo");
}
What is wrong with my predicate, and how can I create a working precondition?
Seems to be a trigger issue. The following works. But maybe someone more familiar with triggers can suggest a better fix.
predicate HasNonWhiteSpace(s: string) {
if s == []
then false
else s[0] !in {' ', '\n', /*'\f',*/ '\r', '\t'/*, '\v'*/} || HasNonWhiteSpace(s[1..])
}
method test1(s: string)
requires HasNonWhiteSpace(s)
{
print s;
}
method test2()
{
test1("./foo");
test1("\t\n ");
test1("d d");
}
BTW: not sure if you meant to require the string being printed to be non-empty. My current solution also requires that.
I'm trying to write a parser for a simple DSL which has a good dozen statements in the form <statementName> <param1> <param2> ... ;, where the number of parameters vary. As the structure of the statements is very similar (all matching the statement name string followed by a series of tokens given by name) and the structure of the made results is very similar (all storing the statement name and a hash of the parameters), I'd like to know how I could specify the wanted result structure without having to repeat myself for each statement action.
Pseudo-code of an action class that would help me to specify such a result structure:
class FooActions {
method *_stmt ($/) {
#result[0] = make string of statement name $/[0];
#result[1] = make hash of $/[1..] with the keys being the name of the rule
at index (i.e. '"var"' for `<var=identifier>` and `"type"` for `<type>`, etc.) and
values being the `.made` results for the rules at index (see below);
return #result;
}
method identifier ($/) { return ~$/ }
method number ($/) { return +$/ }
method type ($/) { return ~$/ }
}
Test file:
use v6;
use Test;
use Foo;
my $s;
$s = 'GoTo 2 ;';
is_deeply Foo::FooGrammar.parse($s).made, ('GoTo', {pos => 2});
$s = 'Set foo 3 ;';
is_deeply Foo::FooGrammar.parse($s).made, ('Set', {var => 'foo', target => 3});
$s = 'Get bar Long ;';
is_deeply Foo::FooGrammar.parse($s).made, ('Get', {var => 'bar', type => 'Long'});
$s = 'Set foo bar ;';
is_deeply Foo::FooGrammar.parse($s).made, ('Set', {var => 'foo', target => 'bar'});
Grammar:
use v6;
unit package Foo;
grammar FooGrammar is export {
rule TOP { <stmt> ';' }
rule type { 'Long' | 'Int' }
rule number { \d+ }
rule identifier { <alpha> \w* }
rule numberOrIdentifier { <number> || <identifier> }
rule goto_stmt { 'GoTo' <pos=number> }
rule set_stmt { 'Set' <var=identifier> <target=numberOrIdentifier> }
rule get_stmt { 'Get' <var=identifier> <type> }
rule stmt { <goto_stmt> || <set_stmt> || <get_stmt> }
}
This approach represents each statement type as a Proto-regex and uses syms to avoid repeating the statement keywords (GoTo etc).
Individual statements don't have action methods. These are handled at the next level (TOP), which uses the caps method on the match, to convert it to a hash.
The <sym> capture is used to extra the keyword. The remainder of the line s converted to a hash. Solution follows:
Grammar and Actions:
use v6;
unit package Foo;
grammar Grammar is export {
rule TOP { <stmt> ';' }
token type { 'Long' | 'Int' }
token number { \d+ }
token identifier { <alpha>\w* }
rule numberOrIdentifier { <number> || <identifier> }
proto rule stmt {*}
rule stmt:sym<GoTo> { <sym> <pos=.number> }
rule stmt:sym<Set> { <sym> <var=.identifier> <target=.numberOrIdentifier> }
rule stmt:sym<Get> { <sym> <var=.identifier> <type> }
}
class Actions {
method number($/) { make +$/ }
method identifier($/) { make ~$/ }
method type($/) { make ~$/ }
method numberOrIdentifier($/) { make ($<number> // $<identifier>).made }
method TOP($/) {
my %caps = $<stmt>.caps;
my $keyw = .Str
given %caps<sym>:delete;
my %args = %caps.pairs.map: {.key => .value.made};
make ($keyw,%args, );
}
}
Tests:
use v6;
use Test;
use Foo;
my $actions = Foo::Actions.new;
my $s;
$s = 'GoTo 2 ;';
is-deeply Foo::Grammar.parse($s, :$actions).made, ('GoTo', {pos => 2});
$s = 'Set foo 3;';
is-deeply Foo::Grammar.parse($s, :$actions).made, ('Set', {var => 'foo', target => 3});
$s = 'Get bar Long ;';
is-deeply Foo::Grammar.parse($s, :$actions).made, ('Get', {var => 'bar', type => 'Long'});
$s = 'Set foo bar ;';
is-deeply Foo::Grammar.parse($s, :$actions).made, ('Set', {var => 'foo', target => 'bar'});
Trying to do something similar to this question except allow underscores from the second character onwards. Not just camel case.
I can test the parser in isolation successfully but when composed in a higher level parser, I get errors
Take the following example:
#![allow(dead_code)]
#[macro_use]
extern crate nom;
use nom::*;
type Bytes<'a> = &'a [u8];
#[derive(Clone,PartialEq,Debug)]
pub enum Statement {
IF,
ELSE,
ASSIGN((String)),
IDENTIFIER(String),
EXPRESSION,
}
fn lowerchar(input: Bytes) -> IResult<Bytes, char>{
if input.is_empty() {
IResult::Incomplete(Needed::Size(1))
} else if (input[0] as char)>='a' && 'z'>=(input[0] as char) {
IResult::Done(&input[1..], input[0] as char)
} else {
IResult::Error(error_code!(ErrorKind::Custom(1)))
}
}
named!(identifier<Bytes,Statement>, map_res!(
recognize!(do_parse!(
lowerchar >>
//alt_complete! is not having the effect it's supposed to so the alternatives need to be ordered from shortest to longest
many0!(alt!(
complete!(is_a!("_"))
| complete!(take_while!(nom::is_alphanumeric))
)) >> ()
)),
|id: Bytes| {
//println!("{:?}",std::str::from_utf8(id).unwrap().to_string());
Result::Ok::<Statement, &str>(
Statement::IDENTIFIER(std::str::from_utf8(id).unwrap().to_string())
)
}
));
named!(expression<Bytes,Statement>, alt_complete!(
identifier //=> { |e: Statement| e }
//| assign_expr //=> { |e: Statement| e }
| if_expr //=> { |e: Statement| e }
));
named!(if_expr<Bytes,Statement>, do_parse!(
if_statement: preceded!(
tag!("if"),
delimited!(tag!("("),expression,tag!(")"))
) >>
//if_statement: delimited!(tag!("("),tag!("hello"),tag!(")")) >>
if_expr: expression >>
//else_statement: opt_res!(tag!("else")) >>
(Statement::IF)
));
#[cfg(test)]
mod tests {
use super::*;
use IResult::*;
//use IResult::Done;
#[test]
fn ident_token() {
assert_eq!(identifier(b"iden___ifiers"), Done::<Bytes, Statement>(b"" , Statement::IDENTIFIER("iden___ifiers".to_string())));
assert_eq!(identifier(b"iden_iFIErs"), Done::<Bytes, Statement>(b"" , Statement::IDENTIFIER("iden_iFIErs".to_string())));
assert_eq!(identifier(b"Iden_iFIErs"), Error(ErrorKind::Custom(1))); // Supposed to fail since not valid
assert_eq!(identifier(b"_den_iFIErs"), Error(ErrorKind::Custom(1))); // Supposed to fail since not valid
}
#[test]
fn if_token() {
assert_eq!(if_expr(b"if(a)a"), Error(ErrorKind::Alt)); // Should have passed
assert_eq!(if_expr(b"if(hello)asdas"), Error(ErrorKind::Alt)); // Should have passed
}
#[test]
fn expr_parser() {
assert_eq!(expression(b"iden___ifiers"), Done::<Bytes, Statement>(b"" , Statement::IDENTIFIER("iden___ifiers".to_string())));
assert_eq!(expression(b"if(hello)asdas"), Error(ErrorKind::Alt)); // Should have been able to recognise an IF statement via expression parser
}
}
I have code similar to:
use std::string::{String};
use std::vec::{Vec};
enum State {
A {
n: usize,
lines: Vec<String>,
},
B {
n: usize,
}
}
fn main() {
use State::*;
let lines = vec!["a", "b", "GO", "c", "GO", "d"];
let mut state = B { n: 0 };
for line in &lines {
state = match state {
A { n, lines } => {
if line == &"GO" {
B { n: n + 1 }
} else {
let mut new_lines = Vec::from(lines);
new_lines.push(line.to_string());
A { n: n, lines: new_lines }
}
},
B { n } => {
A { n: n, lines: vec![line.to_string()] }
},
};
}
let final_n = match state {
A { n, .. } => n,
B { n } => n,
};
println!("final_n = {}", final_n);
}
Rust Playground link: http://is.gd/0QTYaQ
(Note that this is a simplification of the actual code. See the first revision of this question for the full background.)
I want to avoid creating the new_lines vector, so I tried binding the State::A value to a variable and accessing the fields of the value like so:
s # A { .. } => {
if line == &"GO" {
B { n: s.n + 1 }
} else {
s.lines.push(line.to_string());
s
}
},
However, this fails to compile:
ParseState_enum_test.rs:23:28: 23:31 error: attempted access of field `n` on type `State`, but no field with that name was found
ParseState_enum_test.rs:23 B { n: s.n + 1 }
^~~
ParseState_enum_test.rs:19:5: 33:6 note: in this expansion of for loop expansion
ParseState_enum_test.rs:25:21: 25:28 error: attempted access of field `lines` on type `State`, but no field with that name was found
ParseState_enum_test.rs:25 s.lines.push(line.to_string());
^~~~~~~
ParseState_enum_test.rs:19:5: 33:6 note: in this expansion of for loop expansion
error: aborting due to 2 previous errors
How do I access the fields of the value bound to the variable?
EDIT: I am aware of ref mut in pattern binding, but I don't think that this is a good solution in my case. If I use ref mut, then I need to create a clone of the vector because this code does not compile:
A { n, ref mut lines } => {
if line == &"GO" {
B { n: n + 1 }
} else {
lines.push(line.to_string());
A {
n: n,
lines: lines, // error: mismatched types
}
}
},
The following seems to work. Does it solve the problem?
let new_state = match state {
B {n} => A { n: n, lines: vec![line.to_string()] },
A {n, mut lines} => {
match *line {
"GO" => B { n: n + 1 },
_ => {
lines.push(line.to_string());
A{ n:n, lines: lines}
}
}
}
};
state = new_state
https://play.rust-lang.org/?gist=4fa712834999e45ccd4d&version=stable
Let's look at a much simpler version of your issue:
enum Foo {
Alpha { score: u8 },
Beta { lives_left: u8 },
}
fn main() {
let the_value = Foo::Alpha { score: 42 };
match the_value {
alpha_only # Alpha => println!("Score is {}", alpha_only.score),
_ => println!("Dunno what to do!"),
}
}
The problem is that enum variants are not standalone types. That is, there is no way to have a variable of type Foo::Alpha; you can only have it be the type Foo. You can see this in the error message:
attempted access of field score on type Foo, but no field with that name was found
When you use # to bind the entire pattern, you can only know that you are getting something of type Foo.
The normal way of dealing with this is to bind to a component of the item using ref:
match the_value {
Foo::Alpha { ref score } => println!("Score is {}", score),
_ => println!("Dunno what to do!"),
}
And if you need to mutate the value, use ref mut:
match the_value {
Foo::Alpha { ref mut score } => {
*score += 1;
println!("Score is {}", score)
},
_ => println!("Dunno what to do!"),
}
Of if you can consume the value, you don't need ref:
let the_value = Foo::Alpha { score: 42 };
let new_value = match the_value {
Foo::Alpha { score } => Foo::Alpha { score: score + 1 },
Foo::Beta { lives_left } => Foo::Alpha { score: lives_left * 2 },
};