risorse | good unit tests
Questa parte (la sedicesima; qui la prima, qui la seconda, qui la terza, qui la quarta, qui la quinta, qui la sesta, qui la settima, qui l'ottava, qui la nona, qui la decima, qui l'undicesima, qui la dodicesima, qui la tredicesima, qui la quattordicesima e qui la quindicesima) risolve alcuni piccoli problemi riscontrati nell'uso della libreria con Visual Studio Express 2013, GCC 5.1 e Clang 3.6.
È stata aggiunta l'inizializzazione del membro testAlreadyFailed_ dell'oggetto DefaultReport:
class DefaultReport { std::ostream& os_; bool testAlreadyFailed_; std::vector<std::pair<int, std::string>> log_; public: DefaultReport(std::ostream& os = std::cout) : os_(os), testAlreadyFailed_(false) {} ... };
Sono stati esplicitamente disattivati gli operatori di assegnamento delle classi non copiabili:
... struct Expression { ... virtual ~Expression() {} Expression& operator=(const Expression&) = delete; ... }; ... template <typename T> class UnaryExpression : public Expression { ... UnaryExpression(const T& value) : value_(value) {} UnaryExpression& operator=(const UnaryExpression&) = delete; ... }; ... template <typename T, typename U> class BinaryExpression : public Expression { ... BinaryExpression(const T& lhs, const U& rhs) : lhs_(lhs), rhs_(rhs) {} BinaryExpression& operator=(const BinaryExpression&) = delete; ... }; ... template <typename T> class Term { ... Term& operator=(const Term&) = delete; template <typename U> UNEXPECTED_ASSIGNMENT operator=(const U&) const; ... }; ... class DefaultReport { ... public: ... DefaultReport& operator=(const DefaultReport&) = delete; void start() { os_ << "Test suite started..." << std::endl; } ... };
È stato aggiunto il supporto per il confronto dei puntatori con NULL per i sistemi nei quali la costante è un long (tipicamente negli ambienti a 64 bit):
... template <Operator op, typename T> bool compare(T* lhs, long rhs) { return ExprFactory<T*, T*, op>::logAndEvaluate( lhs, reinterpret_cast<T*>(rhs)); } template <Operator op, typename T> bool compare(long lhs, T* rhs) { return ExprFactory<T*, T*, op>::logAndEvaluate( reinterpret_cast<T*>(lhs), rhs); }
Durante la compilazione dei programmi d'esempio, Clang 3.6 genera l'errore in oggetto; per eliminarlo senza rinunciare all'hint dato dalla presenza del nome nel messaggio d'errore, si è uniformata la forma del metodo logAndEvaluate a quello degli operatori della classe Term:
... struct ExprFactory {static bool logAndEvaluate(const T& /*lhs*/, const U& /*rhs*/) {OPERATION_NOT_SUPPORTED dummy;return false;}static OPERATION_NOT_SUPPORTED logAndEvaluate(const T&, const U&); };
È stato aggiunto un esplicito operatore di confronto tra i due tipi interi in oggetto, per evitare l'emissione di un warning relativo a comparazioni tra valori numerici signed/unsigned:
... template <Operator op> bool compare(int lhs, unsigned long long rhs) { return compare<op>(static_cast<unsigned long long>(lhs), rhs); } template <Operator op> bool compare(unsigned long long lhs, int rhs) { return compare<op>(lhs, static_cast<unsigned long long>(rhs)); }
È stato aggiunto il prefisso GUT_ a tutte le macro di supporto, per ridurre le probabilità clashing:
... #define GUT_INT_BASE Dec #define GUT_CHAR_BASE Hex #defineCONCATGUT_CONCAT_(a, b) a ## b #defineCONCAT_GUT_CONCAT(a, b)CONCATGUT_CONCAT_(a, b) #define GUT_INT_TO_STRINGCONCAT_GUT_CONCAT(as, GUT_INT_BASE) #define GUT_CHAR_TO_STRINGCONCAT_GUT_CONCAT(as, GUT_CHAR_BASE) ... #define GUT_PICK_NAME(id_) e_ ## id_, #define GUT_PICK_LABEL(id_) #id_, #define GUT_LEVELS(lambda_) \ lambda_(info) \ lambda_(warning) \ lambda_(error) \ lambda_(fatal) \ enum Level { GUT_LEVELS(GUT_PICK_NAME) }; static std::string level_name[] = { GUT_LEVELS(GUT_PICK_LABEL) }; ...#define MAKE_UNIQUE(name_) CONCAT_(name_, __LINE__)#define GUT_ID(prefix_) GUT_CONCAT(prefix_, __LINE__) #define TEST(name_) \ static voidMAKE_UNIQUEGUT_ID(test_)(); \ gut::Suite::addMAKE_UNIQUEGUT_ID(testAddition_)( name_, &CONCAT_GUT_CONCAT(test_, __LINE__)); \ static voidMAKE_UNIQUEGUT_ID(test_)()
Il Visual Studio Express 2013 emette alcuni warning C4127 spurii quando compila il sorgente al livello di warning 4 (/W4); i messaggi possono essere inibiti puntualmente con un'istruzione pragma:
template <typename T> class UnaryExpression : public Expression { ... virtual std::string toString() const { #ifdef _MSC_VER __pragma(warning(push)) __pragma(warning(disable:4127)) #endif if (HasOperatorString<T>::value) #ifdef _MSC_VER __pragma(warning(pop)) #endif return StringRepr<T, HasOperatorString<T>::value>(value_).str(); else return gut::toString(static_cast<bool>(value_)); } }; ... #define GUT_BEGIN \ do { #ifdef _MSC_VER #define GUT_END \ __pragma(pack(push)) \ __pragma(warning(disable:4127)) \ } while (0) \ __pragma(pack(pop)) #else #define GUT_END \ } while (0) #endif
Il costrutto do/while che caratterizza le macro di test è stato sostituito dall'accoppiata GUT_BEGIN/GUT_END; a titolo d'esempio, la macro CHECK diventa:
#define CHECK(expr_) \ GUT_BEGINdo {\ if (!(gut::Capture()->*expr_)) \ gut::theListener.failure( gut::CheckFailure( #expr_, gut::Expression::last, __FILE__, __LINE__)); \ GUT_END} while (0)
Pagina modificata il 04/06/2015