/**
* Copyright (C) 2012 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
#include
#include
#include
#include
#include "mongo/base/status.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/assert_util.h"
namespace {
using mongo::ErrorCodes;
using mongo::Status;
TEST(Basic, Accessors) {
Status status(ErrorCodes::MaxError, "error", 9999);
ASSERT_EQUALS(status.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(status.reason(), "error");
ASSERT_EQUALS(status.location(), 9999);
}
TEST(Basic, OKIsAValidStatus) {
Status status = Status::OK();
ASSERT_EQUALS(status.code(), ErrorCodes::OK);
}
TEST(Basic, Compare) {
Status errMax(ErrorCodes::MaxError, "error");
ASSERT_TRUE(errMax.compare(errMax));
ASSERT_FALSE(errMax.compare(Status::OK()));
Status errMaxWithLoc(ErrorCodes::MaxError, "error", 9998);
ASSERT_FALSE(errMaxWithLoc.compare(errMax));
}
TEST(Cloning, Copy) {
Status orig(ErrorCodes::MaxError, "error");
ASSERT_EQUALS(orig.refCount(), 1U);
Status dest(orig);
ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(dest.reason(), "error");
ASSERT_EQUALS(dest.refCount(), 2U);
ASSERT_EQUALS(orig.refCount(), 2U);
}
TEST(Cloning, MoveCopyOK) {
Status orig = Status::OK();
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
Status dest(std::move(orig));
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
ASSERT_TRUE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 0U);
}
TEST(Cloning, MoveCopyError) {
Status orig(ErrorCodes::MaxError, "error");
ASSERT_FALSE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 1U);
Status dest(std::move(orig));
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
ASSERT_FALSE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 1U);
ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(dest.reason(), "error");
}
TEST(Cloning, MoveAssignOKToOK) {
Status orig = Status::OK();
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
Status dest = Status::OK();
ASSERT_TRUE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 0U);
dest = std::move(orig);
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
ASSERT_TRUE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 0U);
}
TEST(Cloning, MoveAssignErrorToError) {
Status orig = Status(ErrorCodes::MaxError, "error");
ASSERT_FALSE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 1U);
ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(orig.reason(), "error");
Status dest = Status(ErrorCodes::InternalError, "error2");
ASSERT_FALSE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 1U);
ASSERT_EQUALS(dest.code(), ErrorCodes::InternalError);
ASSERT_EQUALS(dest.reason(), "error2");
dest = std::move(orig);
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
ASSERT_FALSE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 1U);
ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(dest.reason(), "error");
}
TEST(Cloning, MoveAssignErrorToOK) {
Status orig = Status(ErrorCodes::MaxError, "error");
ASSERT_FALSE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 1U);
ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(orig.reason(), "error");
Status dest = Status::OK();
ASSERT_TRUE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 0U);
dest = std::move(orig);
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
ASSERT_FALSE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 1U);
ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(dest.reason(), "error");
}
TEST(Cloning, MoveAssignOKToError) {
Status orig = Status::OK();
ASSERT_TRUE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 0U);
Status dest = Status(ErrorCodes::MaxError, "error");
ASSERT_FALSE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 1U);
ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(dest.reason(), "error");
orig = std::move(dest);
ASSERT_FALSE(orig.isOK());
ASSERT_EQUALS(orig.refCount(), 1U);
ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
ASSERT_EQUALS(orig.reason(), "error");
ASSERT_TRUE(dest.isOK());
ASSERT_EQUALS(dest.refCount(), 0U);
}
TEST(Cloning, OKIsNotRefCounted) {
ASSERT_EQUALS(Status::OK().refCount(), 0U);
Status myOk = Status::OK();
ASSERT_EQUALS(myOk.refCount(), 0U);
ASSERT_EQUALS(Status::OK().refCount(), 0U);
}
TEST(Parsing, CodeToEnum) {
ASSERT_EQUALS(ErrorCodes::TypeMismatch, ErrorCodes::fromInt(ErrorCodes::TypeMismatch));
ASSERT_EQUALS(ErrorCodes::UnknownError, ErrorCodes::fromInt(ErrorCodes::UnknownError));
ASSERT_EQUALS(ErrorCodes::MaxError, ErrorCodes::fromInt(ErrorCodes::MaxError));
ASSERT_EQUALS(ErrorCodes::OK, ErrorCodes::fromInt(0));
}
TEST(Transformers, ExceptionToStatus) {
using mongo::DBException;
using mongo::exceptionToStatus;
auto reason = "oh no";
Status fromDBExcept = [=]() {
try {
throw DBException(reason, ErrorCodes::TypeMismatch);
} catch (...) {
return exceptionToStatus();
}
}();
ASSERT_NOT_OK(fromDBExcept);
ASSERT_EQUALS(fromDBExcept.reason(), reason);
ASSERT_EQUALS(fromDBExcept.code(), ErrorCodes::TypeMismatch);
Status fromStdExcept = [=]() {
try {
throw std::out_of_range(reason);
} catch (...) {
return exceptionToStatus();
}
}();
ASSERT_NOT_OK(fromStdExcept);
// we don't check the exact error message because the type name of the exception
// isn't demangled on windows.
ASSERT_TRUE(fromStdExcept.reason().find(reason) != std::string::npos);
ASSERT_EQUALS(fromStdExcept.code(), ErrorCodes::UnknownError);
class bar : public boost::exception {};
Status fromBoostExcept = [=]() {
try {
throw bar();
} catch (...) {
return exceptionToStatus();
}
}();
ASSERT_NOT_OK(fromBoostExcept);
ASSERT_EQUALS(fromBoostExcept, ErrorCodes::UnknownError);
// Reason should include that it was a boost::exception
ASSERT_TRUE(fromBoostExcept.reason().find("boost::exception") != std::string::npos);
}
} // unnamed namespace