-1

I am building a set of Visual Studio 2015 based Unit Tests, based on Microsoft's native framework. I am using the code show below, which compiles and runs without issue. However, when I run the test, it throws an error (full message below). Before drawGraph, a routine is called which initialises history as equal too float Data[15][5], which is then fully populated with 15, arrays of 5. What am I doing wrong?

vector< vector<float> > history;

float drawGraph(float graph[4][10]) {
    float m, c, j, x1, x2;
    int i = 0;
    while (i < history.size() - 1) {
        j = i + 1;
        x1 = history[i][0];
        x2 = history[j][0];
        m = history[j][3] / history[j][2];
        c = history[i][1] - m*x2;
        i++;
        graph[0][i] = { x1 };
        graph[1][i] = { x2 };
        graph[2][i] = { m };
        graph[3][i] = { c };
    }
    return graph[0][0];
};

Here is my Test Code:

TEST_METHOD(Graph_Equations_Correct) {
    float graph[4][10];
    int i = 1;
    while (i < 10) {
        drawGraph(graph);
        Assert::AreEqual(history[i][4], graph[2][i]);
        i++;
    }
}

This is the result / error it throws:

Result StackTrace: at std::vector >::operator in c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector:line 1233 at UnitTest1::MyTests::Graph_Equations_Correct() in c:\users\george\documents\history testing 2\unittest1\unittest1.cpp:line 32 Result Message: Invalid parameter detected in function std::vector >::operator [], c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector line 1233. Expression: "out of range"

EDIT:

The first test I call is:

TEST_METHOD(Array_Populates)
{
    int i = 0;
    while (i < 10) {
        populateArray(dummyData[i][0], dummyData[i][1]);
        //Assert::AreEqual(history[i][0], dummyData[i][1]);
        i++;
    }
    int j = 0;
    while (j < history.size()) {
        Assert::AreEqual(dummyData[j][0], history.at(j)[1]);
        j++;
    } 
}

Where The Routine in my code is:

void populateArray(int input, int time) {
    values.push_back(time);
    values.push_back(input);
    if (history.size() > 0) {
        values.push_back(values[0] - history.back()[0]);
        values.push_back(values[1] - history.back()[1]);
        values.push_back(values[3] / values[2]);
    }

    history.push_back(values);
    values.clear();
};
George Edwards
  • 8,979
  • 20
  • 78
  • 161
  • In the test before the one in the question, I call a subroutine to populate the array and then verify that it has worked. – George Edwards Dec 15 '15 at 14:39
  • @YSC Sure, please see above – George Edwards Dec 15 '15 at 14:41
  • 1
    `while (i < 10) { i++; ` will let `i` reach 10, which will be out of range for `graph[2][i]` anyway. – Bo Persson Dec 15 '15 at 14:44
  • @BoPersson Yes, edited code above (Please see, as I think that gets around the problem)? However, still get same error – George Edwards Dec 15 '15 at 14:47
  • @GeorgeEdwards `return graph[4][10];` That looks suspicious, no? Those indices are out-of-bounds. – PaulMcKenzie Dec 15 '15 at 14:57
  • @PaulMcKenzie Sorry, not quite sure what is wrong with that? graph is initialised with those dimensions originally, so how could it be our of bounds? – George Edwards Dec 15 '15 at 15:03
  • @GeorgeEdwards Arrays incides start from 0 and go up to `n-1` where `n` is the total number of items. Your array is *declared* as `[4][10]` meaning that the upper limit for indexing the array is `[3][9]`. You are getting confused with `declaration` and `usage`. – PaulMcKenzie Dec 15 '15 at 15:05
  • @PaulMcKenzie yes, but where do I exceed that. In the test, i < 10 should max out at 9. And I reference 2? – George Edwards Dec 15 '15 at 15:08
  • @GeorgeEdwards You're worried about tests, but your code is obviously wrong and invokes undefined behavior on the return of `drawGraph`. – PaulMcKenzie Dec 15 '15 at 15:10
  • @PaulMcKenzie I just can't see where the parameters you referenced are broken? The code does compile and run, so I am not sure where the error is. I just thought that as I am in the process of learning tests, it was more likely that was at fault. – George Edwards Dec 15 '15 at 15:13
  • 1
    @GeorgeEdwards *I just can't see where the parameters you referenced are broken?* -- It is your `return` that is broken. You are accessing an element that is out-of-bounds of the array in the `return` statement, thus invoking undefined behavior. Just because it "runs" doesn't mean it isn't faulty. You start to use that return value, and all heck breaks loose. – PaulMcKenzie Dec 15 '15 at 15:17
  • @PaulMcKenzie Ahhh, I see! Thank you. Although even if I change this to `return graph[0][0]`, I still get the error? – George Edwards Dec 15 '15 at 15:22

1 Answers1

1

The "out of range" error comes from the fact that history.size() is 2 (two push_backs in the call of populateArray); but in your test you check history[i]with i going from 1 to 10.

while (i < 10) {
    i++;
    Assert::AreEqual(history[i][4], graph[2][i]);
}

In your unit tests, where nothing should be considered as 100% sure, prefer std::vecor::at(size_type pos) over std::vector::operator[](size_type pos); more information with this good answer from another SO question.

Additionally, please consider the comment of Bo Persson.

Community
  • 1
  • 1
YSC
  • 38,212
  • 9
  • 96
  • 149