summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/core/constructors.js9
-rw-r--r--src/mongo/scripting/mozjs/bindata.cpp52
-rw-r--r--src/mongo/shell/SConscript3
-rw-r--r--src/mongo/util/uuid.cpp2
-rw-r--r--src/mongo/util/uuid.h7
-rw-r--r--src/mongo/util/uuid_test.cpp11
6 files changed, 66 insertions, 18 deletions
diff --git a/jstests/core/constructors.js b/jstests/core/constructors.js
index 9e2cd26bbe8..b1a6b144896 100644
--- a/jstests/core/constructors.js
+++ b/jstests/core/constructors.js
@@ -196,11 +196,16 @@ var bindataConstructors = {
var uuidConstructors = {
"valid": [
- 'UUID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")',
+ 'UUID("0123456789abcdef0123456789ABCDEF")',
+ 'UUID("0a1A2b3B-4c5C-6d7D-8e9E-AfBFC0D1E3F4")',
+ 'UUID("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")',
+ 'UUID()',
+ UUID().toString(),
],
"invalid": [
'UUID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0)',
- 'UUID()',
+ 'UUID("aaaaaaaa-aaaa-aaaa-aaaaaaaa-aaaaaaaa")',
+ 'UUID("aaaaaaaa-aaaa-aaaa-aaaa-aaaa-aaaaaaa")',
'UUID("aa")',
'UUID("invalidhex")',
'UUID("invalidhexbutstilltherequiredlen")',
diff --git a/src/mongo/scripting/mozjs/bindata.cpp b/src/mongo/scripting/mozjs/bindata.cpp
index d528f6b1651..6d91dea8008 100644
--- a/src/mongo/scripting/mozjs/bindata.cpp
+++ b/src/mongo/scripting/mozjs/bindata.cpp
@@ -33,6 +33,7 @@
#include <cctype>
#include <iomanip>
+#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/scripting/mozjs/implscope.h"
#include "mongo/scripting/mozjs/internedstring.h"
#include "mongo/scripting/mozjs/objectwrapper.h"
@@ -42,6 +43,7 @@
#include "mongo/util/base64.h"
#include "mongo/util/hex.h"
#include "mongo/util/mongoutils/str.h"
+#include "mongo/util/uuid.h"
namespace mongo {
namespace mozjs {
@@ -114,16 +116,30 @@ void BinDataInfo::finalize(JSFreeOp* fop, JSObject* obj) {
}
void BinDataInfo::Functions::UUID::call(JSContext* cx, JS::CallArgs args) {
- if (args.length() != 1)
- uasserted(ErrorCodes::BadValue, "UUID needs 1 argument");
-
- auto arg = args.get(0);
- auto str = ValueWriter(cx, arg).toString();
-
- if (str.length() != 32)
- uasserted(ErrorCodes::BadValue, "UUID string must have 32 characters");
-
- hexToBinData(cx, bdtUUID, arg, args.rval());
+ boost::optional<mongo::UUID> uuid;
+
+ if (args.length() == 0) {
+ uuid = mongo::UUID::gen();
+ } else {
+ uassert(ErrorCodes::BadValue, "UUID needs 0 or 1 arguments", args.length() == 1);
+ auto arg = args.get(0);
+ std::string str = ValueWriter(cx, arg).toString();
+
+ // For backward compatibility quietly accept and convert 32-character hex strings to
+ // BinData(3, ...) as used for the deprecated UUID v3 BSON type.
+ if (str.length() == 32) {
+ hexToBinData(cx, bdtUUID, arg, args.rval());
+ return;
+ }
+ uuid = uassertStatusOK(mongo::UUID::parse(str));
+ };
+ ConstDataRange cdr = uuid->toCDR();
+ std::string encoded = mongo::base64::encode(cdr.data(), cdr.length());
+
+ JS::AutoValueArray<2> newArgs(cx);
+ newArgs[0].setInt32(newUUID);
+ ValueReader(cx, newArgs[1]).fromStringData(encoded);
+ getScope(cx)->getProto<BinDataInfo>().newInstance(newArgs, args.rval());
}
void BinDataInfo::Functions::MD5::call(JSContext* cx, JS::CallArgs args) {
@@ -158,9 +174,21 @@ void BinDataInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
auto str = getEncoded(args.thisv());
str::stream ss;
+ auto binType = o.getNumber(InternedString::type);
+
+ if (binType == newUUID) {
+ auto decoded = mongo::base64::decode(*str);
+
+ // If this is in fact a UUID, use a more friendly string representation.
+ if (decoded.length() == mongo::UUID::kNumBytes) {
+ mongo::UUID uuid = mongo::UUID::fromCDR({decoded.data(), decoded.length()});
+ ss << "UUID(\"" << uuid.toString() << "\")";
+ ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
+ return;
+ }
+ }
- ss << "BinData(" << o.getNumber(InternedString::type) << ",\"" << *str << "\")";
-
+ ss << "BinData(" << binType << ",\"" << *str << "\")";
ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
}
diff --git a/src/mongo/shell/SConscript b/src/mongo/shell/SConscript
index c4f33385344..3e66a33cf4e 100644
--- a/src/mongo/shell/SConscript
+++ b/src/mongo/shell/SConscript
@@ -55,6 +55,7 @@ env.Library(
'mongo.cpp',
],
LIBDEPS=[
- "$BUILD_DIR/mongo/base"
+ "$BUILD_DIR/mongo/base",
+ "$BUILD_DIR/mongo/util/uuid"
],
)
diff --git a/src/mongo/util/uuid.cpp b/src/mongo/util/uuid.cpp
index ca84906eab2..e3326b718bf 100644
--- a/src/mongo/util/uuid.cpp
+++ b/src/mongo/util/uuid.cpp
@@ -60,7 +60,7 @@ StatusWith<UUID> UUID::parse(BSONElement from) {
StatusWith<UUID> UUID::parse(const std::string& s) {
if (!isUUIDString(s)) {
- return {ErrorCodes::InvalidUUID, "Invalid uuid string"};
+ return {ErrorCodes::InvalidUUID, "Invalid UUID string: " + s};
}
UUIDStorage uuid;
diff --git a/src/mongo/util/uuid.h b/src/mongo/util/uuid.h
index 4f86e26aa7c..9e1caa88b6c 100644
--- a/src/mongo/util/uuid.h
+++ b/src/mongo/util/uuid.h
@@ -87,6 +87,13 @@ public:
*/
static UUID parse(const BSONObj& obj);
+ static UUID fromCDR(ConstDataRange cdr) {
+ UUID uuid;
+ invariant(cdr.length() == uuid._uuid.size());
+ memcpy(uuid._uuid.data(), cdr.data(), uuid._uuid.size());
+ return uuid;
+ }
+
/**
* Returns whether this string represents a valid UUID.
*/
diff --git a/src/mongo/util/uuid_test.cpp b/src/mongo/util/uuid_test.cpp
index b0a5d12dada..c6b0388ef06 100644
--- a/src/mongo/util/uuid_test.cpp
+++ b/src/mongo/util/uuid_test.cpp
@@ -141,7 +141,14 @@ TEST(UUIDTest, toAndFromString) {
ASSERT_EQUALS(ErrorCodes::InvalidUUID, UUID::parse("samsamsa-sams-4sam-8sam-samsamsamsam"));
}
-TEST(UUIDTest, toAndFromBSONTest) {
+TEST(UUIDTest, toAndFromCDR) {
+ UUID uuid = UUID::gen();
+ ConstDataRange cdr = uuid.toCDR();
+ UUID roundtripped = UUID::fromCDR(cdr);
+ ASSERT_EQUALS(roundtripped, uuid);
+}
+
+TEST(UUIDTest, toAndFromBSON) {
// UUID -> BSON -> UUID
UUID uuid = UUID::gen();
auto uuidBSON = uuid.toBSON();
@@ -170,7 +177,7 @@ TEST(UUIDTest, toAndFromBSONTest) {
ASSERT_EQUALS(ErrorCodes::InvalidUUID, UUID::parse(bson4.getField("uuid")));
}
-TEST(UUIDTest, toBSONUsingBSONMacroTest) {
+TEST(UUIDTest, toBSONUsingBSONMacro) {
auto uuid = UUID::gen();
auto bson = BSON("myuuid" << uuid);