Unit-testing code with a large number of interdependent conditions - c++

I'm testing a set of output styler classes which style data before outputting it to an output interface. The behavior of each styler is dependent on up to 5 different conditions (at the moment, but a sixth is on the way) with regard to the object being outputted: isKey, isDefault, isEmpty, isReadOnly, isAccessible
So one styler might output nothing if it has readonly data, while another might show "access denied".
At the moment I am testing along these lines, but the tests are exploding as more conditions are added.
{
// isKey, isDefault, isEmpty, isReadOnly, isAccessible
ValueOutputTester::TestConditions conditions = {0, 0, 0, 0, 0};
EXPECT_EQ(valueOutputTester(conditions), accessDeniedOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 0, 0, 1};
EXPECT_EQ(valueOutputTester(conditions), normalOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 0, 1, 0};
EXPECT_EQ(valueOutputTester(conditions), accessDeniedOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 0, 1, 1};
EXPECT_EQ(valueOutputTester(conditions), accessDeniedOutput);
}
{
ValueOutputTester::TestConditions conditions = {0, 0, 1, 0, 0};
EXPECT_EQ(valueOutputTester(conditions), emptyOutput);
}
...
Can you recommend a better way of doing this?

You might write a test helper method that lets you specify condition patterns and that generates all combinations that match the pattern, e.g. assuming -1 means 'either 0 or 1':
TestPattern pattern = {-1, -1, 1, -1, -1};
ExpectForPattern(pattern, emptyOutput);

Related

Arduino Icon Library

I'm working on an Arduino project and I want to display icons on a NeoMatrix 8x8 panel.
Initially, I went in direction that relied on inheritance, and requested some input on Arduino Stack Exchange where I was advised to go another route, and to ask my question elsewhere is it pertained more to C++ than to Arduino.
Instead of relying on inheritance, I was recommended to store my icons in PROGMEM and have the program build the icons from there.
I attempted the approach as much as I could, but I'm not at ease so I'd like some further insight!
The idea is to have a byte array that composes an 8x8 icon.
The values are 0-2, each representing a color set in an RGB struct array.
From what I believe I understand, my byte array stored in PROGMEM is read as a pointer, and needs to be accessed using ppm_read_byte.
I am unsure on how to handle the RGB struct. When I attempt to read it from PROGMEM, it causes my program to crash. So I removed it from PROGMEM, and the icon displays correctly. My byte array is in PROGMEM, but not the colors.
I am aware that I have a serious lack of knowledge about pointers which I need to work on...
Also, the idea is to have a collection of icons, so should I store all my icons (byte arrays and colors) in a header file? Will that not bloat it?
Thank you in advance for insight on this!
header.h
typedef struct {
byte r;
byte g;
byte b;
} RGB;
const byte PROGMEM WifiIcon[8][8] = {
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 2, 2, 2, 2, 1, 1},
{1, 2, 1, 1, 1, 1, 2, 1},
{2, 1, 2, 2, 2, 2, 1, 2},
{1, 2, 1, 1, 1, 1, 2, 1},
{1, 1, 1, 2, 2, 1, 1, 1},
{1, 1, 2, 1, 1, 2, 1, 1},
{0, 0, 0, 1, 1, 0, 0, 0}
};
const RGB WifiIconColors[3] = {
{0, 0, 0},
{0, 0, 0},
{0, 200, 61}
};
ESP8266Neomatrix.ino
#include "header.h"
void printIcon(int startPosition, const byte (&icon)[8][8], const RGB (&colors)[3]){
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
byte currentPixel = pgm_read_byte(&icon[i][j]);
const RGB currentColor = colors[currentPixel];
byte red = currentColor.r;
byte green = currentColor.g;
byte blue = currentColor.b;
matrix.setPixelColor(startPosition++, red, green, blue);
}
}
}
https://gist.github.com/Nate1661/0eea9200e9d1c86187c2acf205ba3602
If you want the RGB data to reside in PROGMEM, since it is not a native type handled by pgm_read_XXX functions, just read it with memcpy_P():
RGB currentColor;
memcpy_P(&currentColor, colors + currentPixel, sizeof(RGB));
If this crashes, then perhaps there is an issue with the value of currentPixel that you read.

C++ Problem filling structs with values from another struct

I'm having an issue trying to figure out why I am not getting the correct functionality with a piece of code. I have looked around to try and find a solution however, I haven't been able to do so. Below is an example of my code:
//Structs
typedef struct
{
int gene[60];
int fitness;
} individual;
typedef struct
{
int cond[5];
int out;
}rule;
//Array of individuals
individual population[P]
int function(individual solution){
int k = 0;
//Array of rules
rule rulebase[10]
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
rulebase[i].cond[j] = solution.gene[k++];
}
rulebase[i].out = solution.gene[k++];
}
for (int i = 0; i < 5; i++){
cout << rulebase[0].cond[i];
}
The solution that is passed into the function is the first individual in 'population' and the gene array contains only binary numbers, for example:
gene = [0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1] //There will be 60 in total
The desired functionality is to fill the rule structures in the rulebase with the values found in the solution. For example, using the example above the first rule in the rulebase will have the values below in the 'cond' array:
[0, 0, 1, 0, 1]
and the 'out' will be the next integer in the solution:
[1]
Then the next rule will be filled with the next values in the solution the same way.
The problem that I am having is the code seems to be filling the 'cond' array of each rule with all of the values in the solution, as oppose to the desired way described above. For example, when I print the genes in 'rulebase[0]' I get:
[0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1]
As oppose to:
[0, 0, 1, 0, 1]
I can't seem to figure out why I am getting this problem as the code looks to me like it should work? Any help would be greatly appreciated as I am seriously struggling!
A rule contains only 5 values in cond, not 10 as you show. Its just your code that prints the values of rulebase[0] that is wrong, i.e. it exceeds array bounds and prints - in addition to the cond-values of rulebase[0] - the values of out and cond of the next rule, which - in memory - come next.

Why doesn't my Sudoku program return an output?

So I have tried to implement a Sudoku via backtracking algorithm. I don't see why my code is not giving an expected output.
What I did was, I created a loop in which it checks for an empty cell (represented with 0) in the sudoku. As it finds it, the co-ordinates for it are passed to a function called possibleEntriescheck(). This function writes into a globally declared array called possibleEntries[9], the digits which can be possibly filled into the cell of which the co-ordinates are passed initially.
I learnt this algorithm from these videos:
https://www.youtube.com/watch?v=NuodN41aK3g
https://www.youtube.com/watch?v=QI0diwmx3OY
The expected output is a solved Sudoku. It doesn't perform expectedly. Rather, it freezes. A little help would mean a lot. Thank you.
#include <stdio.h>
#include <stdlib.h>
int board[9][9] = {
{3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0},
};
int possibleEntries[9];
void possibleEntriescheck(int i, int j)
{
int x,a=0,k,l,y;
for(x=0;x<9;x++)
possibleEntries[x]=0;
for(x=0;x<9;x++)
{
if(board[i][x]!=0)
possibleEntries[board[i][x]-1]=1;
}
for(x=0;x<9;x++)
{
if(board[x][j]!=0)
possibleEntries[board[x][j]-1]=1;
}
if(i==0 || i==1 || i==2)
k=0;
else if(i==3 || i==4 || i==5)
k=3;
else
k=6;
if(j==0 || j==1 || j==2)
l=0;
else if(j==3 || j==4 || j==5)
l=3;
else
l=6;
for(x=k;x<k+3;x++)
{
for(y=l;y<l+3;y++)
if(board[x][y]!=0)
possibleEntries[board[x][y]-1]=1;
}
for(x=0;x<9;x++)
{
if(possibleEntries[x]==0)
possibleEntries[x]=x+1;
else
possibleEntries[x]=0;
}
}
int isFull()
{
int i,j;
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
{
if(board[i][j]==0)
return 0;
}
}
return 1;
}
void solveSudoku()
{
int i,j,x,b=0,k;
if(isFull())
{
printf("The sudoku board is:\n");
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
printf("\t%d",board[i][j]);
printf("\n");
}
}
else
{
for(i=0;i<9;i++)
{
for(j=0;j<9;j++)
{
if(board[i][j]==0)
{
possibleEntriescheck(i,j);
for(x=0;x<9;x++)
{
if(possibleEntries[x]!=0)
{
board[i][j]=possibleEntries[x];
solveSudoku();
board[i][j]=0;
}
}
}
}
}
}
return;
}
int main()
{
solveSudoku();
}
You implemented backtracking incorrectly. As also explained in the video, the actual algorithm should look like this:
solve():
if the sudoku is solved
print field
terminate
x,y = the next vacant field
for each possible value in that field
assign value to x,y
call solve() recursively to try with the assigned value
clear vacant field
Now what your code does is
solve():
if the sudoku is solved
print field
return
for each field in the sudoku
if field is vacant
for each possible value
assign value
solve recursively
reset field to unassigned
Now this actually does solve the sudoku. But there are two problems with this approach:
A: It won't terminate once it's solved the sudoku. Actually this mistake was also in the code presented in the video. A simple return in a recursive call will terminate the method on the current call and continue with the recursion "one call above". So basically the algorithm solves the sudoku in every possible way (provided there are multiple, otherwise it simply tries any possible way of assigning the values).
B: This one's way more serious. Your algorithm doesn't only generate all possible solutions, but it also tries every order of assigning the values it can possibly find. The overhead is gigantic and the reason why your code simply doesn't terminate. Solving the sudoku once already takes quite some time, but your code does so a bazillion times.
If you solve these problems, your code should work find, provided the rest is implemented correctly. I'd also recommend optimizing both the search for vacant fields and the test whether the field is empty, as these can be done fairly simple and will provide some speedup. Generate a list of vacant fields in the beginning, iterate over it (one field for each recursion-level) and terminate once the entire list was processed. E.g.:
solve(vacant, count):
if count == 0
print the field
terminate
x, y = vacant[count]
count++
for each possible value assignable to the field
assign value to x, y
call solve(vacant, count) recursively
clear field
Another problem you will encounter, which will get rather ugly to debug is thanks to this line:
int possibleEntries[9];
Global variables that are used and overwritten in a recursion are a bad idea to say the least. Imagine a possible run of the program like this (ident indicates recursion-level, where no ident means the action is global):
solve
|
---> board empty? Nope
x,y <- next vacant field
possible values <- possible values for x, y
field[x, y] <- first value from possible values
solve
|
---> board empty? Nope
x, y <- next vacant field
possible values <- possible values for x, y (overwrites global variable!!!)
field[x, y] <- first value from possible values
solve
|
---> ...
<--- return
field[x, y] <- second value from possible values (WRONG!!!)
...
The last assignment won't use the list of possible values generated for the field you're currently working on, but of another one that you visited somewhere in the recursion before returning back. You can solve this in two ways:
Iterate from 1 to 9 and check for each number separately whether it can be assigned to the field
Keeping a separate list for each level of recursion

Checkers jump moves (in SFML)

I started coding a few weeks ago and trying out a checker-game right now. I made a class called "figure" and then an array (figure Figure[value]).
I created a 2D field-array in main.cpp and filled it with the numbers for each Figure[]. E.G.:
(main.cpp)
figure Figure[33]; //Figure-array
for (int i = 0; i < 33; i++)
{
Figure[i].id = i;
}
int field[7][7] = { // (I messed the ID's up a little, just ignore it
{0, 0, 1, 2, 3, 0, 0},
{0, 0, 4, 5, 6, 0, 0},
{7, 8, 9, 10, 11, 12, 13}
{14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27},
{0, 0, 28, 29, 30, 0, 0},
{0, 0, 31, 32, 33, 0, 0}
};
for (int y = 0; y < 7; y++) //Field gets filled with figure-values {
for (int x = 0; x < 7; x++)
{
if (field[y][x] != 0)
{
Figure[field[y][x] - 1].setPosition(Vector2i(x + 1, y + 1));
}
}
}
Now I want to make an update function to make them jump over each other etc. My problem here is that i dont know is how to do this properly, I dont know how to write this function completely.Here is what i have already:
(Updatefunction)
void figure::update(int (&field)[7][7], RenderWindow &window) {
Vector2i mouseCoords;
mouseCoords.x = int(Mouse::getPosition(window).x / 114);
mouseCoords.y = int(Mouse::getPosition(window).y / 85);
if ((field[mouseCoords.y][mouseCoords.x] != 0) && (Mouse::isButtonPressed(Mouse::Left)))
{
if ((field[mouseCoords.y][mouseCoords.x] != 0) && !(Mouse::isButtonPressed(Mouse::Left)))
{
selected = true; //selected defined in figure.h
}
}
Vector2i newMouseCoords;
newMouseCoords.x = int(Mouse::getPosition(window).x / 114);
newMouseCoords.y = int(Mouse::getPosition(window).y / 85);
if (selected = true)
{
if ((newMouseCoords.x == mouseCoords.x + 2) && (field[newMouseCoords.y][newMouseCoords.x + 2] != 0))
{
}
}
}
I dont know how to continue here, tips are greatly appreciated!
You haven't provided all your code, so I can't give you an exact solution (and your full listing would probably be too long, and make the question unreadable if you included it, so I wouldn't recommend that).
Here's how I would solve it, given what your existing code looks like:
Do something in this function to handle the appropriate turns. Don't let a player move a piece that isn't theirs.
In your first click check, don't just set a non-piece-specific boolean value to true. Store the "selected piece" in some other variable instead.
Before your second click check, see if the "selected piece" variable is set (maybe check if it is not null - depends on how you define that variable).
Inside the body of your second click check, see if the target position for the selected piece constitutes a valid move. If it doesn't, then display an error to the user.
If the second click check constitutes a valid move, then update the board:
Move the piece, capture any pieces it jumped over, king if necessary
If there is another double-jump move that is possible (there might be two double jumps they could choose from), then allow the player to choose another move. This means more "if" blocks...
If there is a double-jump, then allow the person to back out of the move, since they haven't completed it yet. Uncapture their first jump.
Depending on how strict you are being on the rules, don't allow a person to choose not to do a double-jump. Some checkers rules make capture mandatory if it is possible.
Once all moves are complete, then switch the variable that keeps track of whose turn it is, and unset the "selected piece" variable.
Handle the game end check, and the game over state. This probably should be done after a move.

Is there an easy way to fill a 2d array after initialization?

I currently have a 2d array in my program which stores the coordinates for a cube. It is initialized at the top and is easily filled with the values I want in it like so.
float cubeRef[3][8] = { { -1, 1, 1, -1, -1, 1, 1, -1 },
{ 1, 1, -1, -1, 1, 1, -1, -1 },
{ 1, 1, 1, 1, -1, -1, -1, -1, } };
However during my program the co ordinates change and I have a function which 'resets' them back to the default values you see above. However if I try to reset them using the same method as before.
cubeRef = { { -1, 1, 1, -1, -1, 1, 1, -1 },
{ 1, 1, -1, -1, 1, 1, -1, -1 },
{ 1, 1, 1, 1, -1, -1, -1, -1, } };
It will not work here, with error message "Expression must be a modifiable value".
Why can I not fill a 2d array after initializing the same way I can when I created it? And how can I return the 2d array to it's default values without having to fill each space individually?
You can't assign to an array, it's simply not possible.
You could have two arrays, the one you modify, and one which contains the default values. Then when you want to reset the modifiable array you just copy from the default array, either using std::copy, memcpy or in a loop.
Otherwise you have to manually set each entry, one by one.