@@ -10,10 +10,12 @@ import (
10
10
"net"
11
11
"net/http"
12
12
"net/http/httptest"
13
+ "os"
13
14
"reflect"
14
15
"strconv"
15
16
"strings"
16
17
"sync"
18
+ "sync/atomic"
17
19
"testing"
18
20
"time"
19
21
@@ -33,7 +35,7 @@ func init() {
33
35
}
34
36
35
37
type SimpleServerHandler struct {
36
- n int
38
+ n int32
37
39
}
38
40
39
41
type TestType struct {
@@ -57,14 +59,14 @@ func (h *SimpleServerHandler) Add(in int) error {
57
59
return errors .New ("test" )
58
60
}
59
61
60
- h .n += in
62
+ atomic . AddInt32 ( & h .n , int32 ( in ))
61
63
62
64
return nil
63
65
}
64
66
65
67
func (h * SimpleServerHandler ) AddGet (in int ) int {
66
- h .n += in
67
- return h .n
68
+ atomic . AddInt32 ( & h .n , int32 ( in ))
69
+ return int ( h .n )
68
70
}
69
71
70
72
func (h * SimpleServerHandler ) StringMatch (t TestType , i2 int64 ) (out TestOut , err error ) {
@@ -88,7 +90,7 @@ func TestRawRequests(t *testing.T) {
88
90
testServ := httptest .NewServer (rpcServer )
89
91
defer testServ .Close ()
90
92
91
- tc := func (req , resp string , n int ) func (t * testing.T ) {
93
+ tc := func (req , resp string , n int32 ) func (t * testing.T ) {
92
94
return func (t * testing.T ) {
93
95
rpcHandler .n = 0
94
96
@@ -225,7 +227,7 @@ func TestRPC(t *testing.T) {
225
227
// Add(int) error
226
228
227
229
require .NoError (t , client .Add (2 ))
228
- require .Equal (t , 2 , serverHandler .n )
230
+ require .Equal (t , 2 , int ( serverHandler .n ) )
229
231
230
232
err = client .Add (- 3546 )
231
233
require .EqualError (t , err , "test" )
@@ -234,7 +236,7 @@ func TestRPC(t *testing.T) {
234
236
235
237
n := client .AddGet (3 )
236
238
require .Equal (t , 5 , n )
237
- require .Equal (t , 5 , serverHandler .n )
239
+ require .Equal (t , 5 , int ( serverHandler .n ) )
238
240
239
241
// StringMatch
240
242
@@ -268,7 +270,7 @@ func TestRPC(t *testing.T) {
268
270
269
271
// this one should actually work
270
272
noret .Add (4 )
271
- require .Equal (t , 9 , serverHandler .n )
273
+ require .Equal (t , 9 , int ( serverHandler .n ) )
272
274
closer ()
273
275
274
276
var noparam struct {
@@ -343,7 +345,7 @@ func TestRPCHttpClient(t *testing.T) {
343
345
// Add(int) error
344
346
345
347
require .NoError (t , client .Add (2 ))
346
- require .Equal (t , 2 , serverHandler .n )
348
+ require .Equal (t , 2 , int ( serverHandler .n ) )
347
349
348
350
err = client .Add (- 3546 )
349
351
require .EqualError (t , err , "test" )
@@ -352,7 +354,7 @@ func TestRPCHttpClient(t *testing.T) {
352
354
353
355
n := client .AddGet (3 )
354
356
require .Equal (t , 5 , n )
355
- require .Equal (t , 5 , serverHandler .n )
357
+ require .Equal (t , 5 , int ( serverHandler .n ) )
356
358
357
359
// StringMatch
358
360
@@ -379,7 +381,7 @@ func TestRPCHttpClient(t *testing.T) {
379
381
380
382
// this one should actually work
381
383
noret .Add (4 )
382
- require .Equal (t , 9 , serverHandler .n )
384
+ require .Equal (t , 9 , int ( serverHandler .n ) )
383
385
closer ()
384
386
385
387
var noparam struct {
@@ -429,6 +431,41 @@ func TestRPCHttpClient(t *testing.T) {
429
431
closer ()
430
432
}
431
433
434
+ func TestParallelRPC (t * testing.T ) {
435
+ // setup server
436
+
437
+ serverHandler := & SimpleServerHandler {}
438
+
439
+ rpcServer := NewServer ()
440
+ rpcServer .Register ("SimpleServerHandler" , serverHandler )
441
+
442
+ // httptest stuff
443
+ testServ := httptest .NewServer (rpcServer )
444
+ defer testServ .Close ()
445
+ // setup client
446
+
447
+ var client struct {
448
+ Add func (int ) error
449
+ }
450
+ closer , err := NewClient (context .Background (), "ws://" + testServ .Listener .Addr ().String (), "SimpleServerHandler" , & client , nil )
451
+ require .NoError (t , err )
452
+ defer closer ()
453
+
454
+ var wg sync.WaitGroup
455
+ for i := 0 ; i < 100 ; i ++ {
456
+ wg .Add (1 )
457
+ go func () {
458
+ defer wg .Done ()
459
+ for j := 0 ; j < 100 ; j ++ {
460
+ require .NoError (t , client .Add (2 ))
461
+ }
462
+ }()
463
+ }
464
+ wg .Wait ()
465
+
466
+ require .Equal (t , 20000 , int (serverHandler .n ))
467
+ }
468
+
432
469
type CtxHandler struct {
433
470
lk sync.Mutex
434
471
@@ -1414,3 +1451,110 @@ func TestReverseCallAliased(t *testing.T) {
1414
1451
1415
1452
closer ()
1416
1453
}
1454
+
1455
+ type BigCallTestServerHandler struct {
1456
+ }
1457
+
1458
+ type RecRes struct {
1459
+ I int
1460
+ R []RecRes
1461
+ }
1462
+
1463
+ func (h * BigCallTestServerHandler ) Do () (RecRes , error ) {
1464
+ var res RecRes
1465
+ res .I = 123
1466
+
1467
+ for i := 0 ; i < 15000 ; i ++ {
1468
+ var ires RecRes
1469
+ ires .I = i
1470
+
1471
+ for j := 0 ; j < 15000 ; j ++ {
1472
+ var jres RecRes
1473
+ jres .I = j
1474
+
1475
+ ires .R = append (ires .R , jres )
1476
+ }
1477
+
1478
+ res .R = append (res .R , ires )
1479
+ }
1480
+
1481
+ fmt .Println ("sending result" )
1482
+
1483
+ return res , nil
1484
+ }
1485
+
1486
+ func (h * BigCallTestServerHandler ) Ch (ctx context.Context ) (<- chan int , error ) {
1487
+ out := make (chan int )
1488
+
1489
+ go func () {
1490
+ var i int
1491
+ for {
1492
+ select {
1493
+ case <- ctx .Done ():
1494
+ fmt .Println ("closing" )
1495
+ close (out )
1496
+ return
1497
+ case <- time .After (time .Second ):
1498
+ }
1499
+ fmt .Println ("sending" )
1500
+ out <- i
1501
+ i ++
1502
+ }
1503
+ }()
1504
+
1505
+ return out , nil
1506
+ }
1507
+
1508
+ // TestBigResult tests that the connection doesn't die when sending a large result,
1509
+ // and that requests which happen while a large result is being sent don't fail.
1510
+ func TestBigResult (t * testing.T ) {
1511
+ if os .Getenv ("I_HAVE_A_LOT_OF_MEMORY_AND_TIME" ) != "1" {
1512
+ // needs ~40GB of memory and ~4 minutes to run
1513
+ t .Skip ("skipping test due to requiced resources, set I_HAVE_A_LOT_OF_MEMORY_AND_TIME=1 to run" )
1514
+ }
1515
+
1516
+ // setup server
1517
+
1518
+ serverHandler := & BigCallTestServerHandler {}
1519
+
1520
+ rpcServer := NewServer ()
1521
+ rpcServer .Register ("SimpleServerHandler" , serverHandler )
1522
+
1523
+ // httptest stuff
1524
+ testServ := httptest .NewServer (rpcServer )
1525
+ defer testServ .Close ()
1526
+ // setup client
1527
+
1528
+ var client struct {
1529
+ Do func () (RecRes , error )
1530
+ Ch func (ctx context.Context ) (<- chan int , error )
1531
+ }
1532
+ closer , err := NewClient (context .Background (), "ws://" + testServ .Listener .Addr ().String (), "SimpleServerHandler" , & client , nil )
1533
+ require .NoError (t , err )
1534
+ defer closer ()
1535
+
1536
+ chctx , cancel := context .WithCancel (context .Background ())
1537
+ defer cancel ()
1538
+
1539
+ // client.Ch will generate some requests, which will require websocket locks,
1540
+ // and before fixes in #97 would cause deadlocks / timeouts when combined with
1541
+ // the large result processing from client.Do
1542
+ ch , err := client .Ch (chctx )
1543
+ require .NoError (t , err )
1544
+
1545
+ prevN := <- ch
1546
+
1547
+ go func () {
1548
+ for n := range ch {
1549
+ if n != prevN + 1 {
1550
+ panic ("bad order" )
1551
+ }
1552
+ prevN = n
1553
+ }
1554
+ }()
1555
+
1556
+ _ , err = client .Do ()
1557
+ require .NoError (t , err )
1558
+
1559
+ fmt .Println ("done" )
1560
+ }
0 commit comments