@@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua::Stream;
4
4
5
5
repeat_each(2);
6
6
7
- plan tests => repeat_each() * (blocks() * 3 + 4 );
7
+ plan tests => repeat_each() * (blocks() * 3 + 27 );
8
8
9
9
$ENV {TEST_NGINX_RESOLVER } ||= ' 8.8.8.8' ;
10
10
@@ -1092,3 +1092,315 @@ Hello, 2
1092
1092
***
1093
1093
--- no_error_log
1094
1094
[error]
1095
+
1096
+
1097
+
1098
+ === TEST 28: coroutine.wrap propagates errors to parent coroutine
1099
+ --- stream_server_config
1100
+ content_by_lua_block {
1101
+ local co = coroutine.wrap(function()
1102
+ print("in wrapped coroutine")
1103
+ error("something went wrong")
1104
+ end)
1105
+
1106
+ co()
1107
+
1108
+ ngx.say("ok")
1109
+ }
1110
+ --- stream_response
1111
+ --- error_log eval
1112
+ [
1113
+ qr/\[notice\] .*? in wrapped coroutine/,
1114
+ qr/\[error\] .*? lua entry thread aborted: runtime error: content_by_lua\(nginx\.conf:\d+\):\d+: something went wrong/,
1115
+ "stack traceback:",
1116
+ "coroutine 0:",
1117
+ "coroutine 1:"
1118
+ ]
1119
+
1120
+
1121
+
1122
+ === TEST 29: coroutine.wrap propagates nested errors to parent coroutine
1123
+ Note: in this case, both the error message and the traceback are constructed
1124
+ from co1's stack level.
1125
+ --- stream_server_config
1126
+ content_by_lua_block {
1127
+ local co1 = coroutine.wrap(function()
1128
+ error("something went wrong in co1")
1129
+ end)
1130
+
1131
+ local co2 = coroutine.wrap(function()
1132
+ co1()
1133
+ end)
1134
+
1135
+ co2()
1136
+ }
1137
+ --- stream_response
1138
+ --- error_log eval
1139
+ [
1140
+ qr/\[error\] .*? lua entry thread aborted: runtime error: content_by_lua\(nginx\.conf:\d+\):\d+: something went wrong in co1/,
1141
+ "stack traceback:",
1142
+ "coroutine 0:",
1143
+ "coroutine 1:",
1144
+ "coroutine 2:"
1145
+ ]
1146
+
1147
+
1148
+
1149
+ === TEST 30: coroutine.wrap propagates nested errors with stack level to parent coroutine
1150
+ Note: in this case, the error message is constructed at the entry thread stack
1151
+ level, and the traceback is constructed from co1's stack level.
1152
+ --- stream_server_config
1153
+ content_by_lua_block {
1154
+ local co1 = coroutine.wrap(function()
1155
+ error("something went wrong in co1", 2)
1156
+ end)
1157
+
1158
+ local co2 = coroutine.wrap(function()
1159
+ co1()
1160
+ end)
1161
+
1162
+ co2()
1163
+ }
1164
+ --- stream_response
1165
+ --- error_log eval
1166
+ [
1167
+ qr/\[error\] .*? lua entry thread aborted: runtime error: something went wrong in co1/,
1168
+ "stack traceback:",
1169
+ "coroutine 0:",
1170
+ "coroutine 1:",
1171
+ "coroutine 2:"
1172
+ ]
1173
+
1174
+
1175
+
1176
+ === TEST 31: coroutine.wrap runtime errors do not log errors
1177
+ --- stream_server_config
1178
+ content_by_lua_block {
1179
+ local co = coroutine.wrap(function()
1180
+ print("in wrapped coroutine")
1181
+ error("something went wrong")
1182
+ end)
1183
+
1184
+ co()
1185
+ }
1186
+ --- stream_response
1187
+ --- no_error_log eval
1188
+ [
1189
+ qr/\[error\] .*? lua coroutine: runtime error:/,
1190
+ "[alert]",
1191
+ "[crit]",
1192
+ "[emerg]",
1193
+ "[warn]",
1194
+ ]
1195
+
1196
+
1197
+
1198
+ === TEST 32: coroutine.wrap does not return status boolean on yield
1199
+ --- stream_server_config
1200
+ content_by_lua_block {
1201
+ local co = coroutine.wrap(function()
1202
+ coroutine.yield("ok", "err")
1203
+ end)
1204
+
1205
+ local ret1, ret2 = co()
1206
+
1207
+ ngx.say(ret1, ", ", ret2)
1208
+ }
1209
+ --- stream_response
1210
+ ok, err
1211
+ --- no_error_log
1212
+ [error]
1213
+
1214
+
1215
+
1216
+ === TEST 33: coroutine.wrap does not return status boolean on done
1217
+ --- stream_server_config
1218
+ content_by_lua_block {
1219
+ local co = coroutine.wrap(function() end)
1220
+
1221
+ local ret1 = co()
1222
+
1223
+ ngx.say(ret1)
1224
+ }
1225
+ --- stream_response
1226
+ nil
1227
+ --- no_error_log
1228
+ [emerg]
1229
+ [alert]
1230
+ [crit]
1231
+ [error]
1232
+ [warn]
1233
+
1234
+
1235
+
1236
+ === TEST 34: coroutine.wrap does not return status boolean on error
1237
+ --- SKIP: not supported
1238
+ --- stream_server_config
1239
+ content_by_lua_block {
1240
+ local co = coroutine.wrap(function()
1241
+ error("something went wrong")
1242
+ end)
1243
+
1244
+ local ret1, ret2 = pcall(co)
1245
+
1246
+ ngx.say(ret1, ", ", ret2)
1247
+ }
1248
+ --- response_body
1249
+ false, something went wrong
1250
+ --- no_error_log
1251
+ [error]
1252
+
1253
+
1254
+
1255
+ === TEST 35: coroutine.wrap creates different function refs
1256
+ --- stream_server_config
1257
+ content_by_lua_block {
1258
+ local f = function() end
1259
+ local co = coroutine.wrap(f)
1260
+ local co2 = coroutine.wrap(f)
1261
+
1262
+ ngx.say("co == co2: ", co == co2)
1263
+ }
1264
+ --- stream_response
1265
+ co == co2: false
1266
+ --- no_error_log
1267
+ [emerg]
1268
+ [alert]
1269
+ [crit]
1270
+ [error]
1271
+ [warn]
1272
+
1273
+
1274
+
1275
+ === TEST 36: coroutine.wrap supports yielding and resuming
1276
+ --- stream_server_config
1277
+ content_by_lua_block {
1278
+ local function f()
1279
+ local cnt = 0
1280
+ for i = 1, 20 do
1281
+ ngx.say("co yield: ", cnt)
1282
+ coroutine.yield()
1283
+ cnt = cnt + 1
1284
+ end
1285
+ end
1286
+
1287
+ local f = coroutine.wrap(f)
1288
+ for i = 1, 3 do
1289
+ ngx.say("co resume")
1290
+ f()
1291
+ end
1292
+ }
1293
+ --- stream_response
1294
+ co resume
1295
+ co yield: 0
1296
+ co resume
1297
+ co yield: 1
1298
+ co resume
1299
+ co yield: 2
1300
+ --- no_error_log
1301
+ [error]
1302
+
1303
+
1304
+
1305
+ === TEST 37: coroutine.wrap return values
1306
+ --- stream_server_config
1307
+ content_by_lua_block {
1308
+ local function f()
1309
+ local cnt = 0
1310
+ for i = 1, 20 do
1311
+ coroutine.yield(cnt, cnt + 1)
1312
+ cnt = cnt + 1
1313
+ end
1314
+ end
1315
+
1316
+ local f = coroutine.wrap(f)
1317
+ for i = 1, 3 do
1318
+ ngx.say("co resume")
1319
+ local ret1, ret2 = f()
1320
+ ngx.say("co yield: ", ret1, ", ", ret2)
1321
+ end
1322
+ }
1323
+ --- stream_response
1324
+ co resume
1325
+ co yield: 0, 1
1326
+ co resume
1327
+ co yield: 1, 2
1328
+ co resume
1329
+ co yield: 2, 3
1330
+ --- no_error_log
1331
+ [error]
1332
+
1333
+
1334
+
1335
+ === TEST 38: coroutine.wrap arguments
1336
+ --- stream_server_config
1337
+ content_by_lua_block {
1338
+ local function f(step)
1339
+ local cnt = 0
1340
+ for i = 1, 20 do
1341
+ ngx.say("co yield: ", cnt)
1342
+ coroutine.yield()
1343
+ cnt = cnt + step
1344
+ end
1345
+ end
1346
+
1347
+ local f = coroutine.wrap(f)
1348
+ for i = 1, 3 do
1349
+ ngx.say("co resume")
1350
+ f(i)
1351
+ end
1352
+ }
1353
+ --- stream_response
1354
+ co resume
1355
+ co yield: 0
1356
+ co resume
1357
+ co yield: 1
1358
+ co resume
1359
+ co yield: 2
1360
+ --- no_error_log
1361
+ [error]
1362
+
1363
+
1364
+
1365
+ === TEST 39: coroutine.wrap in init_by_lua propagates errors (orig coroutine.wrap)
1366
+ --- stream_config
1367
+ init_by_lua_block {
1368
+ local co = coroutine.wrap(function()
1369
+ print("in wrapped coroutine")
1370
+ error("something went wrong")
1371
+ end)
1372
+
1373
+ local err = co()
1374
+
1375
+ ngx.log(ngx.CRIT, "err: ", err)
1376
+ }
1377
+ --- stream_server_config
1378
+ content_by_lua_block {
1379
+ ngx.say("ok")
1380
+ }
1381
+ --- must_die
1382
+ --- grep_error_log eval: qr/init_by_lua error: .*? something went wrong/
1383
+ --- grep_error_log_out
1384
+ init_by_lua error: init_by_lua:7: init_by_lua:4: something went wrong
1385
+
1386
+
1387
+
1388
+ === TEST 40: coroutine.resume runtime errors do not log errors
1389
+ --- stream_server_config
1390
+ content_by_lua_block {
1391
+ local function f()
1392
+ error("something went wrong")
1393
+ end
1394
+
1395
+ local ret1, ret2 = coroutine.resume(coroutine.create(f))
1396
+ ngx.say(ret1)
1397
+ ngx.say(ret2)
1398
+ }
1399
+ --- stream_response_like
1400
+ false
1401
+ content_by_lua\(nginx.conf:\d+\):\d+: something went wrong
1402
+ --- no_error_log eval
1403
+ [
1404
+ qr/\[error\] .*? lua coroutine: runtime error:",
1405
+ "stack traceback:",
1406
+ ]
0 commit comments