I’m getting very strange behavior out of a run of the grade-school tests. I can get 8 tests (all) to pass on my home workstation, but when I submit to exercism I get this error:
We received the following error when we ran your code:
make[2]: *** [CMakeFiles/test_grade-school.dir/build.make:70: CMakeFiles/test_grade-school] Error 1
make[1]: *** [CMakeFiles/Makefile2:111: CMakeFiles/test_grade-school.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Also if I uncomment the sixth test, the fifth test decides to fail. The sixth test passes if I comment out the fifth. They all pass if I push the “#if defined(EXERCISM_RUN_ALL_TESTS)” to the bottom
I compared my code to a couple other samples and it’s comparable.
Did i find a bug in catch2?
Thanks,
Matthew
make[2]: *** [CMakeFiles/test_grade-school.dir/build.make:70: CMakeFiles/test_grade-school] Error 1
make[1]: *** [CMakeFiles/Makefile2:111: CMakeFiles/test_grade-school.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
This unhelpful error message is often caused by an exception where the tests do not expect one. Without seeing your code I can only guess that it calls .at()
with a key that does not exist in the std::map
.
Also if I uncomment the sixth test, the fifth test decides to fail. The sixth test passes if I comment out the fifth. They all pass if I push the “#if defined(EXERCISM_RUN_ALL_TESTS)” to the bottom
That sounds either like undefined behavior or state that persists multiple tests.
Please post your solution (in a fenced code blocks) so that the error can be reproduced.
Thanks siebenschaefer.
grade_school.h
#pragma once
// #include <iostream>
#include <map>
#include <vector>
#include <string>
using namespace std;
namespace grade_school {
class school {
public:
const map<int, vector<string>> roster() const;
void add(string, int);
const vector<string> grade(int) const;
private:
map<int, vector<string>> rost;
}; // class school
} // namespace grade_school
grade_school.cpp
#include "grade_school.h"
namespace grade_school {
const map<int, vector<string>> school::roster() const
{
return rost;
}
void school::add(string name, int grade)
{
if(rost.find(grade) == rost.end() || rost[grade].back() < name )
{
rost[grade].push_back(name);
}
else
{
for(auto i = rost[grade].begin(); i < rost[grade].end(); i++)
{
if( name < *i )
{ rost[grade].insert(i, name); }
}
}
} //add
const vector<string> school::grade(int g) const
{
// if(rost.find(g) == rost.end())
// {
// //vector<string> empty {""};
// return vector<string>();
// }
return rost.find(g)->second;
}
} // namespace grade_school
school::grade(int g)
can start with
if(rost.find(g) == rost.end())
{
return vector<string>();
}
I agree, that should work. If I use:
return rost.at(g);
to finish the method, I get a seg violation
That is… if i don’t comment out the previous test:
// TEST_CASE("grade_returns_the_students_in_that_grade_in_alphabetical_order") {
// grade_school::school school_;
// school_.add("Franklin", 5);
// school_.add("Bradley", 5);
// school_.add("Jeff", 1);
// const auto actual = school_.grade(5);
// const vector<string> expected{"Bradley", "Franklin"};
// REQUIRE(expected == actual);
// }
and then it works fine.
This is the failing test (right after the above test):
TEST_CASE("grade_returns_an_empty_array_if_there_are_no_students_in_that_grade") {
const grade_school::school school_{};
const auto actual = school_.grade(1);
REQUIRE(actual.empty());
}
To make things even more interesting, if I reverse the test commenting so the first test (grade_returns…alpahbetical_order) is uncommented and the second is commented (grade_returns_an_empty_array…), then I get 5 out of 5 passing again.
Also if I activate all tests, I get 8 for 8, but on my laptop, not on the exercism host.
After the insert()
in school::add()
we should return or break. Try a web search for “Iterator invalidation”
1 Like
keiraville, that was a very good catch! Of course I should break and return. I added both. Tests have returned to working normally. The exercise now passes when submitted.
Thank you!!
2 Likes