1
2 /**
3 * Copyright (C) 2018-present MongoDB, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the Server Side Public License, version 1,
7 * as published by MongoDB, Inc.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * Server Side Public License for more details.
13 *
14 * You should have received a copy of the Server Side Public License
15 * along with this program. If not, see
16 * <http://www.mongodb.com/licensing/server-side-public-license>.
17 *
18 * As a special exception, the copyright holders give permission to link the
19 * code of portions of this program with the OpenSSL library under certain
20 * conditions as described in each individual source file and distribute
21 * linked combinations including the program with the OpenSSL library. You
22 * must comply with the Server Side Public License in all respects for
23 * all of the code used other than as permitted herein. If you modify file(s)
24 * with this exception, you may extend this exception to your version of the
25 * file(s), but you are not obligated to do so. If you do not wish to do so,
26 * delete this exception statement from your version. If you delete this
27 * exception statement from all source files in the program, then also delete
28 * it in the license file.
29 */
30
31 #include "mongo/platform/basic.h"
32
33 #include <iterator>
34 #include <string>
35 #include <vector>
36
37 #include "mongo/db/jsobj.h"
38 #include "mongo/rpc/command_request.h"
39 #include "mongo/rpc/command_request_builder.h"
40 #include "mongo/unittest/unittest.h"
41 #include "mongo/util/assert_util.h"
42 #include "mongo/util/net/message.h"
43
44 namespace {
45
46 using namespace mongo;
47
TEST(CommandRequest,ParseAllFields)48 TEST(CommandRequest, ParseAllFields) {
49 std::vector<char> opCommandData;
50
51 using std::begin;
52 using std::end;
53
54 auto writeString = [&opCommandData](const std::string& str) {
55 opCommandData.insert(end(opCommandData), begin(str), end(str));
56 opCommandData.push_back('\0');
57 };
58
59 auto writeObj = [&opCommandData](const BSONObj& obj) {
60 opCommandData.insert(end(opCommandData), obj.objdata(), obj.objdata() + obj.objsize());
61 };
62
63 auto database = std::string{"ookokokokok"};
64 writeString(database);
65
66 auto commandName = std::string{"baz"};
67 writeString(commandName);
68
69 BSONObjBuilder commandArgsBob{};
70 commandArgsBob.append("baz", "garply");
71 auto commandArgs = commandArgsBob.done();
72 writeObj(commandArgs);
73
74 BSONObjBuilder metadataBob{};
75 metadataBob.append("foo", "bar");
76 auto metadata = metadataBob.done();
77 writeObj(metadata);
78
79 Message toSend;
80 toSend.setData(dbCommand, opCommandData.data(), opCommandData.size());
81
82 auto opCmd = rpc::ParsedOpCommand::parse(toSend);
83
84 ASSERT_EQUALS(opCmd.body.firstElementFieldName(), commandName);
85 ASSERT_EQUALS(opCmd.database, database);
86 ASSERT_BSONOBJ_EQ(opCmd.metadata, metadata);
87 ASSERT_BSONOBJ_EQ(opCmd.body, commandArgs);
88 }
89
TEST(CommandRequest,EmptyCommandObjThrows)90 TEST(CommandRequest, EmptyCommandObjThrows) {
91 std::vector<char> opCommandData;
92
93 using std::begin;
94 using std::end;
95
96 auto writeString = [&opCommandData](const std::string& str) {
97 opCommandData.insert(end(opCommandData), begin(str), end(str));
98 opCommandData.push_back('\0');
99 };
100
101 auto writeObj = [&opCommandData](const BSONObj& obj) {
102 opCommandData.insert(end(opCommandData), obj.objdata(), obj.objdata() + obj.objsize());
103 };
104
105 auto database = std::string{"someDb"};
106 writeString(database);
107
108 auto commandName = std::string{"baz"};
109 writeString(commandName);
110
111 auto commandArgs = BSONObj();
112 writeObj(commandArgs);
113
114 BSONObjBuilder metadataBob{};
115 metadataBob.append("foo", "bar");
116 auto metadata = metadataBob.done();
117 writeObj(metadata);
118
119 Message msg;
120 msg.setData(dbCommand, opCommandData.data(), opCommandData.size());
121
122 ASSERT_THROWS_CODE(rpc::ParsedOpCommand::parse(msg), AssertionException, 39950);
123 }
124
TEST(CommandRequest,MismatchBetweenCommandNamesThrows)125 TEST(CommandRequest, MismatchBetweenCommandNamesThrows) {
126 std::vector<char> opCommandData;
127
128 using std::begin;
129 using std::end;
130
131 auto writeString = [&opCommandData](const std::string& str) {
132 opCommandData.insert(end(opCommandData), begin(str), end(str));
133 opCommandData.push_back('\0');
134 };
135
136 auto writeObj = [&opCommandData](const BSONObj& obj) {
137 opCommandData.insert(end(opCommandData), obj.objdata(), obj.objdata() + obj.objsize());
138 };
139
140 auto database = std::string{"someDb"};
141 writeString(database);
142
143 auto commandName = std::string{"fakeName"};
144 writeString(commandName);
145
146 auto commandArgs = BSON("realName" << 1);
147 writeObj(commandArgs);
148
149 BSONObjBuilder metadataBob{};
150 metadataBob.append("foo", "bar");
151 auto metadata = metadataBob.done();
152 writeObj(metadata);
153
154 Message msg;
155 msg.setData(dbCommand, opCommandData.data(), opCommandData.size());
156
157 ASSERT_THROWS_CODE(rpc::ParsedOpCommand::parse(msg), AssertionException, 39950);
158 }
159
160 } // namespace
161