I am testing a function to send a mock request to a server using gomega and I want to verify that 1. the request has started 2. the request has completed. For this I am returning two booleans. They should both evaluate to true in the example below but the values will be subject to change. I have tried this:
g := gomega.NewGomegaWithT(t)
...
g.Eventually(func() (bool, bool) {
...
start = false
end = true
if (request.status == "started") {
start = true
}
if (request.status == "complete") {
end = true
}
return start, end
}).Should(Equal((true, true))
But it seems that gomega's Equal() does not handle multiple variables. Is there any way around this? Is it bad practice to evaluate two return values ?
In gomega's doc, It has been said that multiple return is ok to be used.
The function that you pass to Eventually can have more than one return
value. In that case, Eventually passes the first return value to the
matcher and asserts that all other return values are nil or
zero-valued. This allows you to use Eventually with functions that
return a value and an error – a common pattern in Go
In your code, can you change this line
.Should(Equal((true, true)) to .Should(Equal(true, true).
That should fix the problem.
Edit:
I overlooked that Equal only receives one interface parameter. My bad.
For future reference, for comparing multiple values in gomega's eventually,Array of struct (or any datatype) can be useful.
You can use a wrapper function I wrote based on your pseudocode
g := gomega.NewGomegaWithT(t)
...
testedFunc := func() (bool, bool) {
...
start = false
end = true
if (request.status == "started") {
start = true
}
if (request.status == "complete") {
end = true
}
return start, end
}
g.Eventually(func() map[string]bool{
r1,r2 := testedFunc()
return map[string]bool{"start": r1, "end": r2}
}).Should(Equal(map[string]bool{"start": true, "end": true}))
I'm using a map instead of simple r1&r2for verbosity, so, you can see what is actually wrong with the results. In my opinion, it's a bad practice to compare 2 return values unless the second one is an error. You can always combine multiple return values in a single language construct (map, slice, struct, etc.) as I did in my wrapper function. I understand it's hard to do with the async Eventually method, but in general, I'd try to assert each of the return values separately.
Related
I have a list, each element of which contains an inner list.
I need to get an element of the outer list, in which the specified condition is fulfilled for the inner list at least once.
I wrote code like this:
outerList?.find {
!it.items.isNullOrEmpty() && it.items?.any { item ->
item.isVisible == visibility &&
item.progress == currentProgress
} == true
}?.let { outerItem ->
currentItem = outerItem
// here some logic
} ?: run {
currentItem = null
// here some logic
}
But I'm not sure if this code is efficient. Perhaps you should use sequences instead of a list?
Can you please tell me which solution will be the most efficient in terms of execution time and memory consumption for my case?
A sequence isn't going to help here, because you are only performing one operation on the outer list, and one operation on the inner list.
Your !it.items.isNullOrEmpty() check is entirely redundant to the ?.any you follow it up with, so you can remove that. Perhaps the cleanest way to write this would be:
outerList?.find {
it.items.orEmpty().any { item ->
item.isVisible == visibility && item.progress == currentProgress
}
}
Never do this: ?.let { ... } ?: run { }. Aside from being very poor for readability, it is error-prone. If you accidentally return null from the let block, the run block will also be run unexpectedly.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I know that a statement only works if the it evaluates to true by any means such as OR/AND.
I don't understand why computers can't understand this well at least C++.
#include <stdio.h>
#include <stdbool.h>
int main(void) {
// your code goes here
if(false && false)
printf("true\n");
else
printf("false\n");
return 0;
}
Output: false
I know that looking at that code you quickly see that 2 falses and it will be false.
But what if they both became false together as a AND operator doesn't that make them true? not trying to the NOT operator here just don't understand why 2 false's checked together and both give the same output don't make a true?
Now that I wrote more about this seems like it would break alot of programs hehe..
I guess I just wondered into a different way of thinking for a split second and I didn't understand why it didn't work that way.
EDIT: yaa i guess i'll be receiving a bunch of downvotes I guess it's just simply how computers were built they don't have real logic
EDIT 2:
Okay I'll give you a example
Say you have to combine a bunch of packets together not to spam too much little packets.
But there is a catch if those small packets are too large you won't be able to combine them at all just send them as they are.
But lets say you already started combining packets and in the process a large packet arrises so you can't possiblely go on any further you have to quit here and send the current combined packet.
The problem arrises when to break out of the loop of packets in the list..
I am trying to avoid having 2 loops to check the list in advanced to know what to do trying to make it as optimized as possible very important to me.
So I got into a program
if(already building a combined packet boolean AND current_packet->size > MAX_COMBINE_PACKET)
break;
else
//don't try to combine the packets just send normally.
So in this situation I haven't started combining packets and the packet size can fit into a combine packet.
But in this case it doesn't matter if the packet already started combining or hasn't started combining yet but still can be combined it will not try to combine it..
I guess I need to split it up into more if statements.
EDIT 3: the real code
/* pull packets from packet list into buf, and erase/free them */
static int pull_packets(packet_list_t *l, uint8_t *buf, bool cluster) {
int bytes_placed = 0;
int offset = 0;
bool building_cluster = false;
int MAX_CLUSTER_SIZE = 0xFF; //maybe make this a constant? 0xFF bytes is the payload max.
while(l->begin() != l->end()) {
PACKET *p = *l->begin();
/* if you are building a cluster and the packet can't be clustered you can't send a regular packet anymore */
/* otherwise just send it as a regular packet, ignore any clustering */
if(building_cluster && p->len > MAX_CLUSTER_SIZE)
break;
else //else if(!building_cluster && p->len > MAX_CLUSTER_SIZE)
cluster = false;
/* if theres room in the packet for cluster+cluster len+[packet] */
if(cluster && p->len <= (MAX_PACKET - offset)) {
if(!building_cluster) {
//starts a new cluster packet
bytes_placed = build_packet( buf, "BBBX", 0x00, 0x0e, p->len, p->data, p->len);
offset += bytes_placed;
building_cluster = true;
free_packet(p);
l->erase(l->begin());
} else {
//appends to existing cluster packet
bytes_placed = build_packet( &buf[offset], "BX", p->len, p->data, p->len);
offset += bytes_placed;
free_packet(p);
l->erase(l->begin());
}
} else {
/* can't create cluster or cluster is filled up */
if(building_cluster) //has a previous cluster in progress
break;
//cluster is filled up
bytes_placed = build_packet(buf, "X", p->data, p->len);
free_packet(p);
l->erase(l->begin());
return bytes_placed;
}
}
return offset;
}
EDIT 4: ended up using
else if(!building_cluster && p->len > MAX_CLUSTER_SIZE)
I think you are probably confusing false && false with double negation. While double negation becomes affirmative, the way this is expressed in C and C++ is !false or !0.
Your problem description and code is a little vague, but assuming what you really want is:
if not in a combined packet but the current packet is too big,then send the current
if in a combined packet but the current packet is too big,then send the combined, then send the current
if not in a combined packet, but the current packet is small,then break to do the combine
if in a combined packet but the current packet is small,then break to do the combine
Assuming the above is correct, then you only have to check to see if your current packet is small and will fit, otherwise you need to forward stuff.
Looking at your real code, there seems to be some confusing logic around whether you are currently building a cluster, and whether the current packet will fit into your cluster. You will benefit from following a simplified structure. The following pseudocode roughly follows what I had originally suggested, but tailored around how your loop actually operates.
bool start = true;
while (packet = head of list of packets) {
if (packet will fit cluster) {
if (start) {
initialize cluster with packet;
start = false;
} else {
add packet to cluster;
}
remove from head;
} else {
if (start) {
initialize cluster with XL packet;
remove from head;
}
break;
}
}
The logical and has the following value table:
true && true => true
true && false => false
false && true => false
false && false => false
The result is only true if both operands are true. That's just the way it is. That is the real logic. If you don't believe me, just read the Wiki article on boolean algebra. It defines 'and' as above.
If you want a condition that evaluates to true if both operands are of the same value (e.g. both true or both false) then you can just use if(a == b) ..
The && operation is not about agreement.
The false values here are not about negation.
The false values here are values.
The && operation is a function, defined such that true && true yeilds true and any other combination yeilds a value false.
In short a && b is shorthand for
a && b = f(a, b)
where
f(a, b) = { false | a = false, b = false
{ false | a = true, b = false
{ false | a = false, b = true
{ true | a = true, b = true
&& is a computer operation that represents a boolean and operation. It is formally defined within boolean number systems, and typically studied with boolean logic.
This is not about that kind of logic. It's about processing logic. In programming languages, when you have something like:
if (false && false) { ... }
The compiler sees options inside your if because of the &&. Then it evaluates the fisrt one, which is false. From that point, there's no point on evaluating the next expression - since the first one evaluates to false, there's no need to evaluate whatever follows &&, because that's an automatic whole false: false &&.
That's why the following is true:
true && true => true
true && false => false
false && true => false
false && false => false
...which, the way the compiler sees it (as in where it stops evaluating) is:
true && true => true
true && false => false
false && [THIS IS NOT EVEN EVALUATED] => false
false && [THIS IS NOT EVEN EVALUATED] => false
Check out this "truth table":
http://en.wikipedia.org/wiki/Truth_table#Truth_table_for_all_binary_logical_operators
The operation you're looking for is probably "exclusive NOR", which is the "NOT" of "exclusive OR". Exclusive OR is represented by a circle with a + in it in mathematics, and, when used for bitwise computations, by the ^ symbol in C-based languages. For "logical" computations exclusive OR can be represented by the "not equals" operator (and "exclusive NOR" is the "equals" operator).
I have the following code which finds the strings that contain no Alphabets. Cases like mynumber123 shall not be recognized and the numberFinder() should return false and case like 123 shall be recognized and numberFinder() shall return true as well as the begin index of the number.
the constructor:
CaddressParser::CaddressParser(string fileName) //constructor
{
m_fileName=fileName;
int length=getLength(m_fileName.c_str());
m_text =fileReader(m_fileName.c_str());
m_length=length;
}
which initializes a string m_text that contains the contents of a text file
Somewhere along the implementation I come across the following code:
for (i;i<m_length;i++)
{
bool UpperCaseBeforeNoFound=false;
if(this->numberFinder (i).second)
{
//do some calculations.
}
}
the numberFinder function is implemented as follows:
pair <int,bool> CaddressParser::numberFinder(int counter)
{
bool noFound=isdigit(m_text[counter]); //number found? -> true
if(noFound)
{
int end=HouseNoDigits(counter);
if(((counter-1)>=0) && ((counter +end-1) <m_length))
{
if((!(isalpha(m_text[counter-1]))) && (!isalpha(m_text[counter+end-1])))
{
return make_pair(counter,noFound); //return index if true
}
}
}
else return make_pair(0,noFound);
}
Now the problem is for a text file containing the following text "he23 Market street London Q12 H13". I get the error mentioned in the headline and the debugger takes me to the line in the which contains :
if(this->numberFinder (i).second)
I can't figure out why this is happening. Please help me figure it out.
If this condition in CaddressParser::numberFinder(int counter) fails:
if (counter - 1 >= 0 && counter + end - 1 < m_length)
the function will exit without returning a value, resulting in undefined behavior.
The complexity of the conditionals in the function isn't helped by the poor formatting (at least as posted in the question).
You might get the behavior you need by removing the else so any 'fall-through' will return the default pair value (but that will depend on if that's the value you want to really return in that scenario):
pair <int,bool> CaddressParser::numberFinder(int counter)
{
bool noFound=isdigit(m_text[counter]); //number found? -> true
if(noFound)
{
// ...
}
return make_pair(0,noFound);
}
Access Violation error is normally due to NULL reference. One of the function that you are calling is trying to access a NULL pointer. Make sure your isdigit function returns true or false, m_text points to an exiting memory location. If not you need to allocate the memory. You should also check if the fileName is NULL.
Here is an extremely simplified version of a section of code that I am having trouble with.
int i = 0;
int count = 0;
int time = 50;
int steps = 1000;
double Tol = 0.1;
bool crossRes = false;
bool doNext = true;
for (int i=0; i<steps; i++) {
//a lot of operations are done here, I will leave out the details, the only
//important things are that "dif" is calculated each time and doNext either
//stays true or is switched to false
if (doNext = true) {
if (dif <= Tol) count++;
if (count >= time) {
i = steps+1;
crossRes = true;
}
}
}
if (crossRes = true) {
printf("Nothing in this loop should happen if dif is always > Tol
because count should never increment in that case, right?");
}
My issue is that every time it gets done with the for loop, it executes the statements inside the "if (crossRes = true)" brackets even if count is never incremented.
You've made a common (and quite frustrating) mistake:
if (crossRes = true) {
This line assigns crossRes to true and returns true. You're looking to compare crossRes with true, which means you need another equals sign:
if (crossRes == true) {
Or more concisely:
if (crossRes) {
I stand corrected:
if (crossRes)
You wouldn't have this problem if your condition was
if (true = crossRes)
because it wouldn't compile.
`crossRes = true` always evaluates to `true` because it's an assignment, to `true`.
You want `crossRes == true`:
if (crossRes == true) {
printf("Nothing in this loop should happen if dif is always > Tol
because count should never increment in that case, right?");
}
= is assignment, == is equality comparison. You want:
if (crossRes == true) {
You make the same mistake here:
if (doNext = true) { // Bad code
The other answers here have told you the problem. Often your compiler will warn you but a way to ensure that you do not do this is to put the constant term on the left
true == crossRes
that way you get a compiler error instead of a warning and so it can't escape unnoticed since
true = crossRes
wont compile.
First, although a number of people have pointed to the problem with if (crossRes = true), for some reason they haven't (yet, anyway) pointed to the same problem with if (doNext = true).
I'll stick to pointing out that you really want if (crossRes) rather than if (crossRes == true) (or even if (true == crossRes)).
The first reason is that it avoids running into the same problem from a simple typo.
The second is that the result of the comparison is a bool -- so if if (crossRes==true) is necessary, you probably need if (((((crossRes == true) == true) == true) == true) just to be sure (maybe a few more -- you never know). This would, of course, be utterly silly -- you're starting with a bool, so you don't need a comparison to get a bool.
I'd also note for the record, that if you insist on doing a comparison at all, you should almost always use if (x != false) rather than if (x == true). Though it doesn't really apply in C++, in old C that doesn't have an actual Boolean type, any integer type can be used -- but in this case, a comparison to true can give incorrect results. At least normally, false will be 0 and true will be 1 -- but when tested, any non-zero value will count as equivalent to true. For example:
int x = 10;
if (x) // taken
if (x == true) // not taken, but should be.
If you're not starting with a Boolean value as you are here, then the if (<constant> <comparison> <variable>) makes sense and is (IMO) preferred. But when you're starting with a Boolean value anyway, just use it; don't do a comparison to produce another of the same.
I find myself writing code that looks like this a lot:
set<int> affected_items;
while (string code = GetKeyCodeFromSomewhere())
{
if (code == "some constant" || code == "some other constant") {
affected_items.insert(some_constant_id);
} else if (code == "yet another constant" || code == "the constant I didn't mention yet") {
affected_items.insert(some_other_constant_id);
} // else if etc...
}
for (set<int>::iterator it = affected_items.begin(); it != affected_items.end(); it++)
{
switch(*it)
{
case some_constant_id:
RunSomeFunction(with, these, params);
break;
case some_other_constant_id:
RunSomeOtherFunction(with, these, other, params);
break;
// etc...
}
}
The reason I end up writing this code is that I need to only run the functions in the second loop once even if I've received multiple key codes that might cause them to run.
This just doesn't seem like the best way to do it. Is there a neater way?
One approach is to maintain a map from strings to booleans. The main logic can start with something like:
if(done[code])
continue;
done[code] = true;
Then you can perform the appropriate action as soon as you identify the code.
Another approach is to store something executable (object, function pointer, whatever) into a sort of "to do list." For example:
while (string code = GetKeyCodeFromSomewhere())
{
todo[code] = codefor[code];
}
Initialize codefor to contain the appropriate function pointer, or object subclassed from a common base class, for each code value. If the same code shows up more than once, the appropriate entry in todo will just get overwritten with the same value that it already had. At the end, iterate over todo and run all of its members.
Since you don't seem to care about the actual values in the set you could replace it with setting bits in an int. You can also replace the linear time search logic with log time search logic. Here's the final code:
// Ahead of time you build a static map from your strings to bit values.
std::map< std::string, int > codesToValues;
codesToValues[ "some constant" ] = 1;
codesToValues[ "some other constant" ] = 1;
codesToValues[ "yet another constant" ] = 2;
codesToValues[ "the constant I didn't mention yet" ] = 2;
// When you want to do your work
int affected_items = 0;
while (string code = GetKeyCodeFromSomewhere())
affected_items |= codesToValues[ code ];
if( affected_items & 1 )
RunSomeFunction(with, these, params);
if( affected_items & 2 )
RunSomeOtherFunction(with, these, other, params);
// etc...
Its certainly not neater, but you could maintain a set of flags that say whether you've called that specific function or not. That way you avoid having to save things off in a set, you just have the flags.
Since there is (presumably from the way it is written), a fixed at compile time number of different if/else blocks, you can do this pretty easily with a bitset.
Obviously, it will depend on the specific circumstances, but it might be better to have the functions that you call keep track of whether they've already been run and exit early if required.