@@ -85,6 +85,108 @@ TEST_F(ListFamilyTest, Expire) {
85
85
EXPECT_THAT (resp, IntArg (1 ));
86
86
}
87
87
88
+ TEST_F (ListFamilyTest, BLMPopNonblocking) {
89
+ auto resp = Run ({" lpush" , kKey1 , " 1" , " 2" , " 3" , " 4" });
90
+ EXPECT_THAT (resp, IntArg (4 ));
91
+
92
+ resp = Run ({" blmpop" , " 0.01" , " 2" , kKey2 , kKey1 , " LEFT" });
93
+ EXPECT_THAT (resp, RespElementsAre (kKey1 , RespElementsAre (" 4" )));
94
+
95
+ resp = Run ({" blmpop" , " 0.01" , " 2" , kKey2 , kKey1 , " RIGHT" , " COUNT" , " 2" });
96
+ EXPECT_THAT (resp, RespElementsAre (kKey1 , RespElementsAre (" 1" , " 2" )));
97
+
98
+ // If the count exceeds the size of the key's values (but the key is non-empty) then return all of
99
+ // the key's values
100
+ resp = Run ({" blmpop" , " 0.01" , " 1" , kKey1 , " RIGHT" , " COUNT" , " 10" });
101
+ EXPECT_THAT (resp, RespElementsAre (kKey1 , RespElementsAre (" 3" )));
102
+ }
103
+
104
+ TEST_F (ListFamilyTest, BLMPopInvalidSyntax) {
105
+ // Not enough arguments
106
+ auto resp = Run ({" blmpop" , " 0.1" , " 1" , kKey1 });
107
+ EXPECT_THAT (resp, ErrArg (" wrong number of arguments" ));
108
+
109
+ // Timeout is not a float
110
+ resp = Run ({" blmpop" , " foo" , " 1" , kKey1 , " LEFT" , " COUNT" , " 1" });
111
+ EXPECT_THAT (resp, ErrArg (" value is not a valid float" ));
112
+
113
+ // Negative timeout
114
+ resp = Run ({" blmpop" , " -0.01" , " 1" , kKey1 , " LEFT" , " COUNT" , " 1" });
115
+ EXPECT_THAT (resp, ErrArg (" timeout is negative" ));
116
+
117
+ // Zero keys
118
+ resp = Run ({" blmpop" , " 0.01" , " 0" , " LEFT" , " COUNT" , " 1" });
119
+ EXPECT_THAT (resp, ErrArg (" at least 1 input key is needed" ));
120
+
121
+ // Number of keys is not uint
122
+ resp = Run ({" blmpop" , " 0.01" , " aa" , kKey1 , " LEFT" });
123
+ EXPECT_THAT (resp, ErrArg (" value is not an integer or out of range" ));
124
+
125
+ // Missing LEFT/RIGHT
126
+ resp = Run ({" blmpop" , " 0.01" , " 1" , kKey1 , " COUNT" , " 1" });
127
+ EXPECT_THAT (resp, ErrArg (" syntax error" ));
128
+
129
+ // Wrong number of keys
130
+ resp = Run ({" blmpop" , " 0.01" , " 1" , kKey1 , kKey2 , " LEFT" });
131
+ EXPECT_THAT (resp, ErrArg (" syntax error" ));
132
+
133
+ // COUNT without number
134
+ resp = Run ({" blmpop" , " 0.01" , " 1" , kKey1 , " LEFT" , " COUNT" });
135
+ EXPECT_THAT (resp, ErrArg (" syntax error" ));
136
+
137
+ // COUNT is not uint
138
+ resp = Run ({" blmpop" , " 0.01" , " 1" , kKey1 , " LEFT" , " COUNT" , " boo" });
139
+ EXPECT_THAT (resp, ErrArg (" value is not an integer or out of range" ));
140
+
141
+ // Too many arguments
142
+ resp = Run ({" blmpop" , " 0.01" , " 1" , " c" , " LEFT" , " COUNT" , " 2" , " foo" });
143
+ EXPECT_THAT (resp, ErrArg (" syntax error" ));
144
+ }
145
+
146
+ TEST_F (ListFamilyTest, BLMPopBlocking) {
147
+ // attempting to pop from empty key results in blocking and returns
148
+ // null if no values are pushed to the key.
149
+ RespExpr resp;
150
+ auto fb0 = pp_->at (0 )->LaunchFiber (Launch::dispatch, [&] {
151
+ resp = Run ({" blmpop" , " 0.1" , " 1" , kKey1 , " LEFT" });
152
+ });
153
+ ThisFiber::SleepFor (50us);
154
+ ASSERT_TRUE (IsLocked (0 , kKey1 ));
155
+
156
+ fb0.Join ();
157
+ ASSERT_FALSE (IsLocked (0 , kKey1 ));
158
+ EXPECT_THAT (resp, ArgType (RespExpr::NIL));
159
+
160
+ // BLMPOP should not block if there is a non-empty key available
161
+ resp = Run ({" lpush" , kKey1 , " 0" });
162
+ EXPECT_THAT (resp, IntArg (1 ));
163
+
164
+ auto fb1 = pp_->at (1 )->LaunchFiber (Launch::dispatch, [&] {
165
+ resp = Run ({" blmpop" , " 0.1" , " 1" , kKey1 , " LEFT" });
166
+ });
167
+ ThisFiber::SleepFor (50us);
168
+ // shouldn't need to lock the key just pop immediately
169
+ ASSERT_FALSE (IsLocked (0 , kKey1 ));
170
+ fb1.Join ();
171
+
172
+ // should block until a key is available and then immediately unblock
173
+ auto fb2 = pp_->at (2 )->LaunchFiber (Launch::dispatch, [&] {
174
+ resp = Run ({" blmpop" , " 0.1" , " 1" , kKey1 , " LEFT" });
175
+ });
176
+ ThisFiber::SleepFor (50us);
177
+
178
+ // key should be locked while waiting
179
+ ASSERT_TRUE (IsLocked (0 , kKey1 ));
180
+
181
+ auto push_resp = Run ({" lpush" , kKey1 , " 1" });
182
+ EXPECT_THAT (push_resp, IntArg (1 ));
183
+
184
+ // key should be unlocked after being inserted to
185
+ fb2.Join ();
186
+ ASSERT_FALSE (IsLocked (0 , kKey1 ));
187
+ EXPECT_THAT (resp, RespElementsAre (kKey1 , RespElementsAre (" 1" )));
188
+ }
189
+
88
190
TEST_F (ListFamilyTest, BLPopUnblocking) {
89
191
auto resp = Run ({" lpush" , kKey1 , " 1" });
90
192
EXPECT_THAT (resp, IntArg (1 ));
0 commit comments