aboutsummaryrefslogblamecommitdiffstats
path: root/erts/emulator/test/socket_SUITE.erl
blob: 410582f4a1215c43f5f6281fcba769fabe423973 (plain) (tree)
1
2
3
4
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400
12401
12402
12403
12404
12405
12406
12407
12408
12409
12410
12411
12412
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
12423
12424
12425
12426
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486
12487
12488
12489
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518
12519
12520
12521
12522
12523
12524
12525
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536
12537
12538
12539
12540
12541
12542
12543
12544
12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
12580
12581
12582
12583
12584
12585
12586
12587
12588
12589
12590
12591
12592
12593
12594
12595
12596
12597
12598
12599
12600
12601
12602
12603
12604
12605
12606
12607
12608
12609
12610
12611
12612
12613
12614
12615
12616
12617
12618
12619
12620
12621
12622
12623
12624
12625
12626
12627
12628
12629
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639
12640
12641
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652


                   
                                                        















                                                                           









                                                                         



                                                          


                                                              
                                           








                                                   
                              
                                           





                                                         
 






                                                 
                                              
                                              
                                                   


             


                            
                             

                                     

                                     
                                          
                                          
                                          
                                          
                                    
                                    
                                          
                                          
 
                             
                              
                                          
                                          
                                    
                                          
                                      
                                     
                                    
                                  
                                     
                                       
                                      
                                     

                                      
 
 
                               
                                      
                                            
                                                  
                                          
 
                                         



                               

                               

                            

                              










                                

                               
                                  

                                      
                                      

                                      
                                      
 

                                    
                                    

                                        
                                        

                                       
                                       

                                       
                                       

                                        
                                        
 

                                    
                                    
                                       
                                       
                                       
 

                                                 
                                                 

                                                    
                                                    
 
                           
                                             
                                             
                                             
 

                                                      
                                                      

                                                       
                                                       
                                                      
                                                      
                                                      


                                                            
                                                            

                                                             
                                                             


                                                            
                                                            

                                                             
                                                             
                                                            
                                                            
                                                            
 

                                                            
                                                            
                                                             
                                                             
                                                             
 


                                                       
                                        




                                         
 





                                         
 




                                         
                                        


                                                       


















                                          
                                         


                                                      


















                                         
                                        


                                                      


















                                          
                                         


                                                      


















                                         
                                        


                                                      


















                                          
                                         


                                                           


















                                          
                                         


                                                           

                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           
                                          
                                          
                                          


                                                          


















                                          
                                         


                                                          

                                          
                                          
                                           
                                           


                                           
                                          


                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           
                                          
                                          
                                          


                                                          


















                                          
                                         


                                                          

                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           
                                          

                                          
 


                   


                                      


                   
 




                                                                         
                                              

                          

                                             



                                   
 


                                          
 



                                                                       


                               
 

                                   
 






                                                                         






















                                                                        

            
                                                   
                                                        
                                                         
                                                         
                                                           

                                                               

































































                                                                          
 
                                                 



              
                       
                        
                        
                          
                                 

      




                   
                    

                               
                               

                               
                                    
                                    
                                    
                                    
                              
                              

                                    

      

                    
                        
                                    
                                    
                              
                                    
                                
                               
                              
                            
                               
                                 
                                


                               

      

                      





                              
                                
                                      
                                           

      




                                   
                              
     



                         

                         

                      

                        











                          

      

                                                                     
                         
     
                                
                             

                                
      
 
                                                                         
                                                     



                                
                                
                                

                                

      




                                                                    
                              
 

                                  
                                  
 

                                 
                                 

                                 
                                 

                                  

                                  






                                                                     
                              

                                 

                                 

      





                                                                             
                                           

                                              

                                              

      
 

                  







                                         
                                       
                                       

                                      
 

                               

                                                
                                                

                                                 
                                                 
                                                
                                                

                                               
 

                                     

                                                      
                                                      

                                                       

                                                      
 

                                     

                                                      
                                                      

                                                       
                                                       
                                                      
                                                      
                                                      


                                                      
                                                      
                                                       

                                                       
      
    

                
                                                   
                          

                                                  
                          

                                                  
                          

                                                       
                           

                                                      
                           

                                                      
                          
 



                                              






                                              











                                              
                                  





                                   

                                 
 



                                              

                                  
 

                                   
 
                                  

                                 
 



                                              







                                   

      











































                                              
 
                                             






                                             

















































                                              












































                                             
                                             






                                             

















































                                              












































                                             
                                                  






                                                  

















































                                                  














                                                  
                                    


                                     
                                     

                                    

                                    







                                                  
                                    


                                     
                                     

                                    

                                    







                                                  
                                    


                                     
                                     

                                    

                                    

      
                                                 






                                                 

















































                                                 














                                                  
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    

      
                                                 






                                                 

















































                                                 














                                                  
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    

      






                                                                         
                         
















                                                              
        

                   
                           

       




                                                
                          



                                                                
                                                                            







                                                
                         




                                                         
                                 


                                                   





                                   


                                
                      


           











                                                        
 
                
                                                                         

                                                                         

















                                                                         
                                          



                                     






















                                                                                    



















                                                                         





                                                                         
 






                                                                
                  






                                                       










                                                                         
                  






                                                       



                                                                         








                                                                       
                                                         


















                                                                         
                                                         









                                                                         















































                                                                           






                                                                               

                                       




                                                                            




























                                                                               
                              

                                                  


                               
                           


                                                     

 
 








                                                                         
                  








                                                                 









                                                                         
                       






                                                                



                                                    








                                                                 



                                                          

 

                                                                         






                                                                
                  


                                                  

                                                                  



                                                                        


                                                                 


                                                              
                                                                          
                                                                           


                                                                 
                                                                                    





                                                               
                                               



                                                          

 

                                                                         








                                                                



                                                    


































                                                                                    
                                     


                                   





                                                                    
                                                                 

                                                       
                        
 
                                     



                                                                  

                              
                                                              







                                                                                



                                                       

                                                           

                                                        
 
                                     


                                                                  


                                                         
                                                              







                                                                                



                                                       

                                                           



                                                                           
                                                      

                                         
                                                                           









                                                                          


                                                                           
                                                      


                                                                           









                                                                          

                                      

                                           
                                                                 
                                                   
                                   


                                                                                    



                                                               

                                      

                                           
                                                                 
                                                   
                                   


                                                                                    



                                                               


                               
                           
          

                                                     











                                                                          
                   








                                                         









                                                                          
                                           






                                                          
                                                         







                                                         
                                                   



                                                          

 

                                                                         






                                                                           
                   















                                                                 
                                               



                                                          

 

                                                                         
                                                                           
                                           






                                                                
                                                         






                                                              






                                                                         

                                                                         



                                                               

                                                           



                                                               



                                                 








                                                                         
                                     
                                  

                


                                               
                                                       








                                                                   

                                                      
                                                                 


                                                   
                                          
                                                     
                                                                     






                                                               









                                                                                

                                                          
                                                                            








                                                               
                                           





                                                                              
                                                                   

                             



                                              
                                                                      
                        



                                                       
                                                                            
                                                               



                                                    

                                              
                                                               



                                                         






                                                    

                                                   
                                                                 



                                                      
                                                                          
                        
                                
                                                         

                                                 

                                                 
                                                                   

                             



                                                      
                                                                       






                                                                    
                                                   
                                                   
                                                          

                                         




                                                                 




                                                                               







                                                                   
                        

                               
                           



                

                                               



                                                                               
                                                               








                                                                              
                                                  







                                                                           
                                                                          

                                   
                                          
                                                     
                                                                     






                                                              
                                                                    
                                                         

                                             



                                                    

                                              
                                                             





                                                       
                                                                       
                        
                                       
                                                            

                                                    

                                              
                                                                



                                                       
                                                                        
                        



                                                        

                                                   
                                                                 


                                                    



                                                         

                                                 
                                                                   





                                                      
                                                                       





                                                                    
                                  

                                           
                                                                 
                                                   
                                   




                                                                               



                                                           
                        

                               
                           


















                                                                
                                                    



                                                   
                                                                            





                                                                         
                                                          



                                                    
                                                                   




                                                            
                                                                  

                             
                              

                                                             
                                                                   



                                                       
                                                                    


                                                       
                                                                   


                                                                  
                                                                    



                                                            
                                                                     


                                                       
                                                                     


                                                                
                                                                      



                                                          
                                                                       


                                                       
                                                                       





                                                       
                                                           



                                                      
                                                          




                                                               
                                                           



                                                      
                                                          




                                                               
                           

          
                                
                                                        
 
                                
                                                        
                            



                                                 
                                                              
 
                                                     



                                                                         
 












                                                                           





                                                         
                                                 


                                                    
























                                                                         
                                                                 


















































                                                                            




































                                                                          









































                                                                              

                                                                 




































                                                                             



                                                                             





































                                                                                






















                                                                            



































                                                                          



























































































                                                                            






































                                                                     















































                                                                         























                                                                      








                                                                         

                                                              





















                                                                      

                                                             







                                                           























                                                                         
                                                                 































                                                                             
                                                                   

                                                                



                                                                               


                                                                      
                                                                   













                                                                    


                                                                            






                                                               
                                                 







                                                                
                                                   
                                              
                                                                 

                             
 
























































                                                                           
                                                                 









                                                                





                                                        



























                                                                             
                                                                       
























                                                                        
                                               







                                                          
                                                 
                                              
                                                                 
























































































                                                                                
                                                       
                                                    
                                                                       























                                                                          
                                                     
                                                    
                                                                       

























































                                                                         





                                                                          
                                   





                                                          
                                    
















                                                                         






















                                                                           
                                                     
                                             

                                                             












                                                                         


















                                                                   
                                                                 





































                                                                      
                                                                   



















































                                                                           
                                                                   

































































































                                                                              

                                                                 

























































                                                                          
                                                                   


















































































































































































































                                                                            





                                                              
                            






                                                                         








                                                                  
                   





                                                                          

                                                             












                                                                         







                                                                 
                   





                                                                      

                                                             












                                                                         

















                                                                   
                                                                 


































                                                                             
                                                      



















































































































































                                                                                
 
                                                                













                                                                       

                                                               
































                                                                         
                                                                 





































                                                                      
                                                                            









































































































































                                                                                  
























                                                                         






















                                                                         


















                                                                   
                                                                 
























































                                                                      
                                                                            



















































































                                                                                

                                                                 
























































































































































































                                                                            

                                                                         
                                                                          













                                                                          
                                             

                                                             












                                                                         
                                                                         













                                                                      
                                             

                                                             






























                                                                         
                                                                 

































                                                                    
                                                      













                                                                                
                                                                               





                                                                         
                                                                            























































                                                                           
                                                      













                                                                                
                                                                               





                                                                         
                                                                            













                                                                       
                                                              






















                                                                                  









                                                                























































































                                                                               































                                                                            



































                                                                       

























                                                                         

                                                               
































                                                                         
                                                                 





































                                                                      
                                                                            
















                                                                                  
                                                                                 





                                                                         
                                                                            







                                                              
 









                                                                       
 































                                                                        
                                                      













                                                                                  
                                                                                 





                                                                         
                                                                            








































































































































































































                                                                                    


 

                                                                         



































































                                                                         
                                                                 
























































                                                                      
                                                                            
















                                                                                
                                                                               




























































                                                                         
                                                      













                                                                                
                                                                               





                                                                         
                                                                            












































                                                                                  

                                                                 




































































































































































































































































































                                                                               







                                                                         
 





                                                                     
                  

                                                      
 
                               






                                                 

































                                                                          





                                                                        



























                                                                      


                                                                                






                                                                     








                                                                                                  





                                                                     









                                                                                























































































































































                                                                               
                                      
                                                                    
                                                        
                             
                                      
 
                                  
                                                                   
                                                        
                             
                                      



                                                                         




































                                                                   
                                                                 



















































































































































































































































                                                                                  
                                                                 




































































































































































































































































































































































































                                                                                   





                                                                        
                   

                                                                  
 
                                           






                                                 




                                 
                                                               






                                                                   
                        

                                   





















                                                                            
                                                
                                                       
                                                                  

                             
                                            
                                                       
                                                                     



























                                                                            
                                            
                                                       
                                                              
                             
 
                        

                               

                                                      
                                                                


                                                               


                               
                           











                                                                    






                                                                   













                                                                     
                                                             

                             
                                                      
                                                       
                                                                      


























                                                                            
                                                     
                                                       
                                                                 



                                                       
                                                                   
                             












                                                                  

                               

                                                       
                                                           

                             
                                              
                                                      
                                                          
                                                           







                                                         
                           

          
                                             
                           


                                                                    


                                             
                                                     
                                                                    
 



                                               
                           


                                                                    


                                            
                                                     



                                                                    
 


                                                                         


















































                                                                         
                                                                 





































































































































































































































































                                                                               







                                                                         
 

                                                                
                             
       
                           
       
                                                     
                   
                                              
                               
                
                   



                                                       

                                                     
 







                                                             


                                            

























                                                                     




                                                                         
                             
       
                           
       
                                                     
                   
                               
                                                                  
                   



                                                        

                                                     


                                                                         




                                                                       
 
                                
                                  





                                               


                                                                  




                                                                   




                                                      
                                                                 
                                                        










                                                                   
                                                                     







                                                               

                                                                
                        
                                           
                                                             
                                                                   

                             


                                     
                                                      
                                                                       



                                                                    

                              






                                                               

                               
                           

          
               
         









                                                                   

                             

                             

                                                      
                                                                 
                                                        
                        

                                                  
                                                                        




                                                                        

                                                 

                              



                                                                  
                        





































                                                                             



                                                    














                                                                           



                                                                            

                                              



                                                    














                                                                             



                                                    





















                                                                         


                              


















                                                                   
                                                                 

                                                        
                                        


                                                                

                             

                                                                       
                                                                               

                                                              
                        










                                                                  
 









                                                                       
                        




                                                                         
                                    



                                                    

                        

                                    











                                                                  
                                                       
                                                           

                             
                                       
                                                      
                                                          


                                                                   
                        

                               
                           

          
                                 
                                                               
                                                                       
 




                                                                       
                                 

                                                          
                                                                       
 
                            
                                                     

 

                                 
                                                 

                            

                                    




                                                                              
                                        
                                                               
                                                        

                 

                                  

                                             




                                                    
 














                                                            
 







                                                        
 
                                                                   
                                          

































                                                                              
 
                                                                

                                            

                                              
                           
                        
                                 

                                
                                               

                       

                                                          
                

                                        
               
                          
                                       
                                     
             
                      
        






                                                  




                                                                         
                            
       
                          
       
                                                    
                   

                              

                                                                  
                





                                                                         
                            
       
                          
       
                                                    
                   
                              
                                           
                   

                                                                   
                



                                                                         





                                                      
                                                                 








































                                                                                  
                                                 















                                                                           
                           

          
                                 
                                                        
 
                         
                                     




                                                                         







                                                                     
                   















                                                                         
                   
                               
                                           
                   












                                                                         
                                                       





                                                                


                                                      
                                                                 























                                                                   
                                           
                                                              
                                                                    

                             


                                             
                                                       
                                                                      
                        






                                                                             

                                                                            







                                                                                  
                                                 






                                                                           
                                             
                                              
                                                               

                             

                             

                                                       
                                                                
                             
                        



                                                    
                                                          


                               
                           







                                 
                                                                


                                                        
                        


                                                                

                             
                                           
                                                       
                                                             
                             


                                        

                                                       
                                                                      
                        













                                                                             
                                                                                 
                                                 

                                               


                                                                       



                                                                           
                                             
                                                       
                                                               

                             

                             
                                     
                                                      
                                                                       



                                                                    



                               
                           

























                                                                
                                                    

                             
                                                      
                                                          
                                                                                   
                                                      




                                                                           
                                                           

                             
                                                       
                                                           
                                                                     




                                                                           
                                                           

                             
                                                       
                                                           
                                                                     




                                                           
                                                               



                                                           
                                                               



                                                           
                                                               



                                         
                                                        
                                                           
                                                                       
                        
                                                         
                                                           
                                                                       
                        
                                                         
                                                           
                                                                       

                        
                     

                                                           
                                                        

                             

                                                          






                                                                              
                        

                                                           
                                                        

                             

                                                          






                                                                              
                        

                                                           
                                                        

                             

                                                          






                                                                              


                               
                           

          
                                        
                               
                                                                                
 
                                         
                                                    
                                                                                
    
                                         
                                    
                                                                                
 
                                 


                                                              
                                                              
 
                            
                                                                               




                                                                         

                                                             
                          
       
                        
       
                                                  




                                                





                                                                         
                          
       
                        
       
                                                  




                                                 





                                                                         
                            
       
                          
       





                                                     





                                                                         
                            
       
                          
       





                                                      





                                                                         
                             
       
                           
       
                                                     




                                                   





                                                                         
                             
       
                           
       
                                                     




                                                    






                                                                         
                          
       
                        
       
                                                  




                                               






                                                                         
                          
       
                        
       
                                                  




                                                 





                                                                         
                          
       
                        
       
                                                  
                   

                            


                                                                        
                                                  

                                                     





                                                                         
                          
       
                        
       
                                                  
                   
                            
                                           
                   

                                                

                                                                  
                                      

                                                          
                                                          




                                                              



                                                                         
                                
                                  





                                               
                                                       
                                                         
                        




                                                                   



                                                      
                                                                 
                                                        










                                                                   
                                                                     










                                                               
                                           
                                                             
                                                                   

                             

                                   
                                                      
                                              
                                                                           
                        
                                    








                                                              


                                                                               
                                                  
                                                                             





                                                               
                                           
                                                                                 
                                                 

                                               


                                                                       



                                                                           

                                                           
                                                                    





                                                      
                                                                       



                                                                    













                                                          
                           






                                               
                                                               

                                                             
                        




                                                                   



                                                                           

                                                                 
                                                                          










                                                                   
                                                                    






                                                         
                                           
                                                       
                                                             





                                                       
                                                                       

                             
                                                            






                                                      
                                                                       



                                                                    








                                                         
                           





                                    


                                                                   

                                    


                                                                   




                                                       
                                                       



                                                      
                                                                               
                                                            


                                                            
                                                                       





                                                                            
                                                             

                             
                                               
                                                       
                                                                 




                                                             
                                                                   



                                                       
                                                                        




                                                       
                                                           



                                                      






                                                                       

                                               
                                                       
                                                           



                                                      







                                                                             


                               
                           


          
                                
                                
                                                              
 
                                
                                
                                                              
 
                                

                                                 
                                                              
 
                            
                                                     
 





                                                                         
                              
       
                            
       
                                                      
                   

                                


                                                                            
                                                  
                                                     
                





                                                                         
                              
       
                            
       
                                                      
                   
                                
                                           
                   


                                                                            
                                                  
                                                     
                



                                                                         
                                




                                                      
                                                                 






















                                                                  


                                                                               
                                                  

                                                              
                                         




                                                               

                                                                                  
                                                 







                                                                           


                                                   
                                                                    




                                            
                           

          
                                
                                                        
    
                         
                                     
 





                                                                         
                             
       
                           
       
                                                     
                   

                               


                                                                        
                                                  
                                                     
                





                                                                         
                             
       
                           
       
                                                     
                   
                               
                                           
                   


                                                                        
                                                  
                                                     
                



                                                                         

                                                                
                             
       
                           
       
                                                     
                   

                               


                                                                        
                                                  

                                                     





                                                                         
                             
       
                           
       
                                                     
                   
                               
                                           
                   


                                                                        
                                                  

                                                     
 
 



                                                                         
                                                                         





                                                                         
                                                                           

                                                               
                                    
       
                                  
       
                                                            
                  
                                      
                   


                                                    
                                                        




                                                                         
                                                                           

                                                               
                                    
       
                                  
       
                                                            
                  
                                      
                                           
                   


                                                    
                                                        




                                                                         
                                                                           






                                                                        
                  
                                      
                                                         
                   









                                                                           

                                                              
                                    
       
                                  
       
                                                            
                  
                                      
                   


                                                   
                                                        








                                                                         
                                    
       
                                  
       
                                                            
                  
                                      
                                           
                   


                                                   
                                                        



                                                                         








                                                                           
                  
                                      
                                                         
                   








                                                                         
 
                                   




                                               
                                                       
                                                         
                        




                                                                   

                             










                                                                   
                                           
                                                                     
                                                                   

                             
 
                                   
                                                                        

                                                      
                                                                       



                                                                    

                              
 
                               
                           
          
 









                                                                  
                                                    


                                         
                                                  
                                                                           
                                                     

                                                         
                                                                 
                                                                                
                                           








                                                                      
                                                        


                                               
                                                   





                                                              
                        

                                                                           
                                               
                                                                 
                                                                                

                                                                                


                                                 
                                                                                 


                                                                        
 
                               
                           
          
 
                                        
                                                     
 
                                

                                                              
 
                         
                                            

 
 

                                                                         
                                                               
                  







                                                                      
 
                                  
       
                                
       
                                                          
                   
                                    
                   

                                                                  

                                                   
                                                             







                                                                         
                                  
       
                                
       
                                                          
                   
                                    
                                           
                   

                                                                  

                                                   
                                                             



                                                                         

                                                                    
                                         


















                                                                         
 
                                        
                                                              
                                                              
                                                                      




                                               
                                                       
                                                         









                                                                   
                                                                 
                                                   


                                             
                                                       
                                                                     






                                                               












                                                                                

                                                          
                                                                            









                                                               





                                                                   
                                                                   



                             
                                             
                                                      







                                                                              
                        
                                  


                                                       

                                                                                   




                                                               

                                              
                                                               

                             

                                                                
                                                                           



                                                                
                                                                           



                                                                
                                                                           



                                                       
                                                                      
                             
                        
                                             









                                                                   
                                                              
                             

                        
                             

                                                      
                                                                       



                                                                    

                              





                                                               


                                                                               



                                                               







                                                                       


                               
                           

          

                                                         




                                               
                                                                   

                                                            
                        
                                    



                                                                   




                                                                     

                                              
                                                             



                             

                                                     





                                                                               
                        
                                               
                                              
                                                                 

                             
                                              
                                                                
                                                                         
                                             
                                             
                                                                           
                                                               
                                                 

                                                                            


                                                                     
                                                                          
                                                                    


                                        
                                                  
                                              
                                                                    

                             

                             
                                     
                                                      
                                                                       



                                                                    




                               
                           







                                                                    
                                                       





                                                                   

                        
                             

                                                      
                                                                 
                                                        


                                             
                                                       
                                                                     






                                                              
                                                                    

                                                         






                                                         
                                           
                                                       
                                                             



                             
                                              

                                                      










                                                                               






                                                                               
                        
                                       

                                                                 
                        
                                              
                                                       
                                                                


                             
                             

                                                      
                                                                       




                                                                    

                                  




                                                                 




                                                                               
                                                           
                                                   




                                                         
                           









                                                                











                                                                











                                                                
                                                    



                                                     
                                                                        

                                                                           


                                                    

                        

                                           
                                                                            
                                                              

                             

                                                      
                                                                

                                           
                                                                            
                                                              



                                                      
                                                                

                                           
                                                                            
                                                              



                                                      
                                                                




                                                    
                                                    



                                                    
                                                              


                           
                                                         



                                                     
                                                                             

                             
                              
                                                        

                                                                         

                             
                                                   
                                                      
                                                                       
                        
                                                  
                                                    
                                                                      
                        
                                                      
                                                      
                                                                         
                        
                                                      
                                                      
                                                                         
                        
                                                      
                                                      
                                                                         
                        
                              
                                                                          
                                                      
                                                              

                             

                                                      
                                                                      

                                                         
                                                      
                                                                            
                        
                                                         
                                                      
                                                                            
                        
                                                         
                                                      
                                                                            


                        

                                                    
                                                        



                                                   





                                                                    
                        

                                                      
                                                        



                                                     





                                                                      


                                                      
                                                        



                                                     





                                                                      


                                                      
                                                        

                             

                                                     





                                                                      


                                                      
                                                        



                                                     





                                                                      



                               
                           

          
                                  
                             
                                                                 
 
                                   
                                                            
                                                                     

                                   
                                                                     

                                   
                                                                     
 
                                
                                
                                                              
 
                                




                                                    
                                                              
 
                         


                                                          




                                                                         








                                                                   
                   

                                        

                                                                                  















                                                                         
                   
                                        
                                           
                   
                                                                                  
























                                                                                  








                                                                         
                                             

                                 
                                                       
                                                         





                                                                   

                             

                                                      
                                                                 
                                                        

                                 

                                                                         



                                                               
                                                           







                                                                                


                                                            
                                                                   



                             
                                                         
                                                      





                                                                            
                        
                                           









                                                                            
                                                         
                                              
                                                             



                                                       
                                                                          

                                  




                                                                 




                                                                               

                                                           






                                                                  
                                            
                                              
                                                              





                                                      
                                                                          



                                                                    



                               
                           






                                 
                                                               
                                                                       







                                                                   
                                                             



                             
                                           
                                                       
                                                                         
                           


                                                                








                                                                  
                                                  
                                              
                                                                    





                                                      
                                                                       



                                                                    



                               
                           





























                                                                
                                                    



                                                         
                                                                                 
                                                     




                                                                       
                                                          



                                                             
                                                                        




                                                                       
                                                          



                                                             
                                                                        




                                                                       
                                                          



                                                             
                                                                        









                                                                             
                                                                   
                                                         
                                                             

                             
                              
                                                                   
                                                         
                                                             

                             
                              
                                                                   
                                                         
                                                             

                             
                              
                                                                             
                                                         
                                                                       

                             
                                                                       
                                                         
                                                                   


                                                                
                                                              

                             
                                                          
                                                         
                                                                    


                                                               
                                                                          


                                                               
                                                                          


                                                               
                                                                          
                        



                                                             
                                                        



                                                            





                                                                         


                                                             
                                                        



                                                            





                                                                         


                                                             
                                                        



                                                            





                                                                         


                                                         
                                                        



                                                        





                                                                         



                               
                           




                                          
                                                                            


                                                           
                                                                           

                                              
                                                                           

                                              
                                                                           


                                                         


                                                          
                                                              

                         


                                                               




                                                                         


                                                                    
                                     
       
                                   
       
                                                             
                   
                                       
                   

                                                                     

                                                   
                                                             







                                                                         
                                     
       
                                   
       
                                                             
                   
                                    
                                           
                   

                                                                     

                                                   
                                                             




                                                                         
                                                                    





















                                                                         










                                                                             


                                                   














                                                                         
                                           
                   

                                                                             


                                                   



                                                             
 

                                                                         






















                                                                             


                                                                      

                  
                                      
       
                                    
       
                                                              
                   
                                        
                   
                                                  

                                                              




                                                                         


                                                                      

                  
                                      
       
                                    
       
                                                              
                   
                                        
                                           
                   
                                                   

                                                              



                                                                         





















                                                                         
 

                                         
         
                                             
                                               
                                
                                                       
                                                         





                                                                   

                             

                                                      
                                                                 
                                                   
                        

                                             
                                                       
                                                                     
                                            
                                                              




                                                    



                                                               




                                                    

                                              

                                           

                                                                     

                             
 





                                                                              



                                                    
                                      

                                                                        

                                                  
                                            


                                                                     



                                                    
                                                     
                                              
                                                                       

                             
                                            
                                                       
                                                                          
                        
                                  





                                                               






                                                                                  

                                                                   
                                                     


                                                  


                                                                  

                                                    

                              
                                            
                                              
                                                              

                             


                                                             
                                                      
                                                                       



                                                                    

                              











                                                                       
                        


                                                                   

                             

                                              
                                                            


                           


                                                                           
                        









                                                                  
                        
                                                    
                                              
                                                                     



                                                   

                                                                       




                                                                    
                        

                               
                           




                             

                                                      


                                                                

                                                      


                                                                

                                                      


                                                                

                                                      



                                                                


                                                      
                                                    

                             



                                                                              

                        



                                                                    

                             


                                                                     
                        




                                                                    

                             


                                                                     
                        




                                                                    

                             


                                                                     

                        
 
                           








                                                                             

                             



                                                                       

                             



                                                                       

                             
                              


                                                                         

                             


                                                                               
                        

                                                                  
                                                              

                             


                                                                      
                        


                                                                              
                        


                                                                              
                        


                                                                              

                        
 
                        

                                                               
                                                        

                             

                                                              

                                                              
                                                                      


                                                    
                        

                                                               
                                                        

                             

                                                              

                                                              
                                                                      


                                                    
                        

                                                               
                                                        

                             

                                                              

                                                              
                                                                      


                                                    
                        

                                                           
                                                        

                             

                                                          

                                                              
                                                                      


                                                    
                        
 
 
                               
                           

          
 












                                                                             

                                  



                                                    
                                                              

                         
                                                                         

 
 








                                                                          
 
                                  
       
                                
       
                                                          
                   
                                    
                   
                                                                  
                                                  







                                                                         
                                                                  

                  
                                  
       
                                
       
                                                          
                   
                                    
                                           
                   
                                                                  
                                                   






                                                                         





















                                                                         
 




                                                             

                                             
                                 
                                
                                                       
                                                         
                        








                                                                   
                                                                 


                                                        

                                                                         






                                                               










                                                                                











                                                               








                                                                              






















                                                                                    
                                                  

















                                                                                    
                                                  



















                                                                                    
                                                  



































































                                                                        
 















































                                                                       





                                                               






                                                                                  

                                                                    
                                                     


                                                    


































                                                                                  

                                                 


















                                                                   



                                                                          







































































































































































































































































































































































































                                                                                

                               
                                               


                            

                                  
                                                             
                                          
                                                      
                                                   




                                                     
                                       

                                                      
                             

                 


                                
                                            





                                               
                                         
                                          
                                              
                     





                                                                     






                                        
                                          

                                  







                                                         




                                                  
                                      


                                                  
                                               










                                                
                                     


                                         
                              

                          

                                                     
                              
                                    




















                                                                    
                                                                     





                                                            

                                               





















                                                
                                             



                                           


                                                     

                                    
 















                                                                         
                   

                                       

                                                                     















                                                                         
                   
                                       
                                           
                   

                                                                     

                                                   





















                                                                         




                                                                         



                                                                   
                  



                                                                          
                                                         
  
 
                                               
       
                                             
       
                                                                       
                   
                                                 
                   







                                                              
                                               



                                                                  


                
                                                                         



                                                                   

                  
                                               
       
                                             
       

                                                                       
                                           
                   








                                                              
































                                                                         



                                                                  


                





                                                                         
















                                                                   
                                                                   
                                                                 


                                                        

                                                                      






                                                               









                                                                                

                                                          
                                                                            









                                                               




                                                                              







                                                                       
                                                                         

                            
                                                                  

                                                       





                                                                              



                                                    





                                                                   





                                                               
                                                 
                                                       
                                                                    
                        



                                                             
                        






                                                                           



                                                    



                                                             
                        


                                                                    
                        



                                                             
                        





                                                                            




                                                    




                                                             
 
                       








                                                                       










                                                                 

                                         


                                                                 
                                              
                                   




                                                                               

                                                            





                                                                   

























                                                                   
                                                                        

                                                              

                                                 






                                                                  



                                                                    








                                                                   



                                                                          





























                                                                        
                                                                     







                                                                
                                           

                                                       
                                                                         

                                                                           
                                                                      



                                                    


                                                  


                                                                      
                                                        

                                                        

                                                                  
                        
                                           
                                              
                                                             


                             

                                               
                                           



























































































































































                                                                                

                             




                                                                 

                             



                                                                 

                             




                                                                     

                             



                                                             

                             




                                                                 


                             


                                                             

                             





                                                                 
                        





                                                              

                             





                                                                  
                        



                                                    


                                                        

                                                   

                                                              
                                                                       

























                                                                       
                                                              
                                                              
                                                               

                                                              


                                                              
                                                              

                                                              

                                  


                                                             


                                                              
                                                     
 
 
                                     
                  
                                                     


                            

                                  
                                                             
                                          
                                                      
                                                   










                                                         
                                       

                                                      
                             

                 


                                
                                            

       

                                               

                             
                                         
                                          
                                              





                                       

                                        
                                          

                                  







                                                         



                                
                                                  

                                        









                                                       
 


                                           






                                          

















                                            
                                     
                                         

                              
                              

                          

                                                     
                              
                                    

        

                                                   









                                                                    
                                      
                      
                                                                


                                         








                                                             

                 

                                 




                                            
                                             

                                         
                                          


                                                

                                                 

                        


                                                 





                                              
                                             



                                           


                                                     

                                    

                                                           





                                                                         
                                                                   
                                                                     

                                                                  

                  
                                                  
       
                                                
       

                                                                          

                                  













                                                                      




                                                    
                                                                  



                                                                         
                                                                   
                                                                     

                                                                  

                  
                                                  
       
                                                
       

                                                                          
                                           
                   
                                  










                                                                      

                                                                   
                                   




                                                    
                                                                  



                                                                         



















                                                                          






                                                                              




















                                                                              










                                                                          
                   

                                             

                                                
















                                                                          
                   
                                             
                                           
                   























                                                                          



                                                                   

                                                                         

















                                                                   
                                                                 


                                                        

                                                                      






                                                               










                                                                                











                                                               







                                                                  
































                                                                               
                                                                             






                                                                        
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                              






                                                                               
                                          
















                                                                                    
                                                                    

                                                          

                                                                    





















                                                                       




                                                                 




                                                                               

                                                            
                                                      
                                                          











                                                                   
                                                           












                                                                   
                                                                                 

                                                              

                                                 


















                                                                    



                                                                          




                                                        
                                                                  











                                                               
                                                                       










                                                                    
                                                                     










                                                                

                                                                   














                                                                           
                                                                       









                                                                       


                             


                                                       

                                                                    





                                                                           
                        
















                                                                             



                                                    
















                                                                             



                                                    








                                                                             
                        









                                                                        
                        
















                                                                             


                                                    
                        
















                                                                             



                                                    








                                                                             
                        









                                                                        
                        
















                                                                             



                                                    








                                                                             
                        






                                                                        

                                                    
                              
                        








                                                                             
                        









                                                                        
                        








                                                                             
                        






                                                                        



                                                    
















                                                                        
                                              

                                                                        



                                                   



                                                                            



                                                                    

                              


                                                           

                             




                                                                
                        


                                                   
                        





                                                                 

                        


                               
 





                                                                

                             



                                                                

                        



                                                    

                             



                                                                                

                        




                                                              

                             


                                                                   
                        



                                                    
                                                               

                             
                              


                                                                

                             




                                                                   

                             




                                                                     
                        






                                                       
                        
 



                                                                        

                             





















                                                                                 


                                                    
                        



                                                                                   

                             





















                                                                                  


                                                    
                        



                                                    
                                                        

                             

                                                   

                                                              

                                                                       


                                                    
                        

                                                    
                                                        

                             

                                                   

                                                              

                                                                       


                                                    



                               
                           

          


                                                              
 


                                                              

                                  

                                                 
                                                              

                         





                                                     
                                                     

                            
                                 
                                                                 





                                                            
                                             




















                                                                   


                                      
                                            
                                                                   
                                          
                                                            

                                                         




                                                     
                                               
                                                
                                              







                                              
                                          

                                  







                                                         



















                                                        
                                           


                                               
                              

                          

                                                     
                              
                                    
        
 







                                                         

 

                                                                         












                                                                            
                   

                          

                                                      
                                                
                                               


                                                                      
                

 
 
                                                                         












                                                                            
                   

                          
                                                      
                                           
                   
                                                 




























                                                                            


                                                                      
                
 

                                                                         

                                                                      



                                                                       
                                                    
 
                                                     
       
                                                   
       



                                                                             
                   
                                  
                                                
                                               

                                                
                                                                      



                                                                         
                                                                      




                                                                       
                                                    
 
                                                     
       
                                                   
       



                                                                             
                                           
                   

                                                 
                                               

                                                
                                                                      


                
 
                                                                         





                                                                       




























                                                                             
                                                   
 
                                                    
       
                                                  
       
                                                                            
                   


                                                      
                   
                                                
                                               


                                                                      
                


                                                                         





                                                                       
                                                   
 
                                                    
       
                                                  
       



                                                                            
                                           
                   
                                  
                                                 
                                               


                                                                      
                
 

 
                                                                         
















                                                                            



                                                      







                                                                      








                                                               


                                                                         


















                                                                                  
                                               



















                                                                                  
                   


                                                            
                                           
                   
                                                 
                                               













                                                                            




























                                                                                  












                                                                                   
                                               






















                                                                                   
                                           

                                  
                                                 
                                               







                                                                            




























                                                                                   





                                                                       
                                                   
 
                                                          
       
                                                        
       



                                                                                  
                   
                                  
                                                
                                               


                                                                            









                                                                            
                                                   
 
                                                          
       
                                                        
       



                                                                                  
                                           
                   
                                  
                                                 
                                               


                                                                            



                                                                         



























                                                                                  

                                                                   



                                                                       
                                                    
 
                                                           
       
                                                         
       



                                                                                   
                   
                                  
                                                
                                               

                                                
                                                                            
                
 
 
                                                                         
                                                                            




                                                                       
                                                    
 
                                                           
       
                                                         
       



                                                                                   
                                           
                   
                                  

                                                 

                                                
                                                                            
                
 
 
                                                                         



























                                                                                   












                                                                                  

                          
                                                            
                                                                           

                                  
                                                
                                               


                                                                            


                









                                                                              













                                                                                  

                          
                                                            



                                                                     
                   
                                  
                                                 
                                               


                                                                            




                                                                         




























                                                                                  






                                                                       
 








                                                                                  
                                  
                                                
                                               



                                                                            
 
 
















                                                                                  
                                           
                   
                                  
                                                 
                                               






                                                                            



























                                                                                  


















                                                                                   
                                               






















                                                                                   
                                           
                   
                                  

                                                 







                                                                            




























                                                                                   










                                                            


                                                                            






                                                          





                                                          
               


                                                              








                                                      











                                                                      




                                                                    
                                                                    

                                                                 
                                           








                                                                               



                                                                    

                                                                 
                                           








                                                                               


                            
                                                                   



                                                                         












                                                                   
 


                                                      
                                                                 


                                                        

                                                                      






                                                               









                                                                                

                                                          
                                                                            




                                                               
                                        
                                                                          

                                         




                                               




                                                                              




































                                                                                 

                                                       
                                                                            





































































                                                                          




                                                                 




                                                                               

                                                            
                                                      
                                                          




























                                                                                  

                                                 



















                                                                           
                                            




                                                        

                                                                         





















































































































































































































                                                                                
                                                                    













                                                                               





                                                                                
                                                             

                                                                               


                                                                       

                                                                               

                                                                        



                                                    


                                                            

                                                    


                                                                      
                                                                       









































                                                                       
                                                                  
























                                                                   
                                                             

                                                 
                                                            

                                                         
                               







































                                                          
                                                 


                                                                                


                                            

                                                                     


                                                                

                                                                       

                                                                      




                                                                












                                                                                 
                                             

                            

                                
                                                                                
                                          

                                                                




                                                                 
                                                                         

                                                        
                                          
                               

                 
                              


                                            
















                                                            
                                                       

                     
                                                                 










                                                     

                                                        
                          
                                                              


                  
                                                              













                                                                
                                                         
                                                                  
                                                                                    

                                              

                                                                  

                                                
                                                                      


                                                                       

                                                            

                                                                    


                                            

                                                            


                                    

                                                   
                     
                               





                                         
                                          

                                  









                                                         









                                              
                                        

                              
                              

                          

                                                     
                              
                                    

        

    



















                                                                      
                              












                                                                              
                              












                                                                


                                                               

                           



                                                                                   


                             





                                             
 



                                        
 







                                         
 

                                                                         
                    
 










                                                            
 







                                                                            
                             











                                                            

 


                                                                    

                                                                




                                                                                   

                                                                





                                                                                   

                                                             





                                                                                
 













                                                                   
 


                                                      
                                                                 

                                                        
                                   

                                                                      






                                                              








                                                                    









































                                                                            




                                                                             



                                                                       
 







                                                                     
                                            
                                                       
                                                                    








                                                                      
 











                                                                    


                                                                 






                                                                                 


                             








































































                                                                                  

                                                 




















                                                                     
                                            



                                                        

                                                                         
















































































































































































































































                                                                                
 

                                                                  
                                                                  












































                                                                   

                                                                 









                                                                     
                                       



                                                                     
                                                          








                                                                              


                                                 
                
                          

                                                           




                                                       


                                                






                                           
                                                                             

                            


                                        
                                                                                 

                                                 
                                          

                                                         
                                      

                                                                  

                                        

                                                                           
                         
                                                         
                                   
                                                     
                                               
                                   


                               
                                      


                                            

       

                                                                
                             

                                                                 






                                                                          
                                                                      
                                                                          

                                                    

                                                

                                                                        




















                                                                               

                                                  

                                                                             
                                                           




                                                      

                                                          
                                          
                                                                          
                                                           
                                                   
                                                  
                                                           

                                            
                                                           
                 


                                       

        











                                                                     















































                                                                 

                                             







                                       
                                          






                                  
                                 

                              
                              

                          

                                                 
                              
                                    


        



                                                                         




                                                    




                                      

                                                            
                                           
                      







                                                                         





                                                                    





                                      

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      
                    
                          

















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      
                    
                          

















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      
                    
                          

















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      
                    
                          

















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      









                                                                         























                                                                         









                                                        

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      







                                                                         























                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      









                                                                         
                                                       








                                                   

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      









                                                                         























                                                                         









                                                       

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      







                                                                         

                                                                    























                                                                         









                                                       

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      









                                                                         























                                                                         









                                                       

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      







                                                                         























                                                                         
 





















                                                                   
                                                                















                                                          










                                         
             
                  



                                   

                   
                     

                                                                               



                                  

                                                                     














                                                                         





















                                                                   

                                                 







                                                                  













                                                                              

                                                    


                                                                              







                                                                 





                                                                   





















































                                                                             







                                                                   
















                                                                   

                                                 




















                                                                      

























                                                                               












                                                                               


                                                                    










                                                                             





































































                                                                          






                                                                            






                                                            





                                                          






















































                                                                       






                                                            




                                                    




                                                                          












































































                                                                                            

                                                              







                                                              
                                                     

                                                                        
                                                     
                                                


                                                      






                                                                        

                                                                             



                                                         
                                                          
                                                      


                                                                               

                                                                             
                                                


                                                      


                                                         
                                                          
                                                      


                                                                               

                                                                         
















































































































































































                                                                                    





                                                                   
                             














                                                                            


                                                                             







                                                           
















                                                         




                             
    














                                                                         




































































                                                                 




                                                                         




                                             





                                 



                                                                       






                                                                                  




                                                                           

                
 
                                                                          





                                                                     


                                         

            

                                          
                                  
 


                                                              
                                  

                                         

                               
                          
                         

        








                                                               

        
                                     
                      











                                                          
        

                                         
 






                                                       
 
                                              
                        
                                                                  
                                                               

                                                                   


                                        


                                                 


 


                                                                         
























                                                                  
 

                                                 
 

                                                  
 
 









                                                   
 
 
 
 







                                                                      
                                   

                     
                                  
            



                                          
                                         
               


        
                                                                  
                                                                     

                          





                                     





                                                                         























                                                                         
 


                                









                                                                         
           
 

                                         































                                                                         

                                           




                                                                             

                                    



                                                                             















                                                                   
                   








                                     
                                                                              




                                                                
                         







                                                              

                           
                                   

                          
                                 
                                          
         
                                                                      




                                                          
                 







                                                        


        

                                   
 


















                                                   
   

                                                                         


                         


                         


                           




                                       
 

                       
 















                                                                        

 

                            
 











                                                                          
 

             
 
          



                                                     
%%
%% %CopyrightBegin%
%% 
%% Copyright Ericsson AB 2018-2019. All Rights Reserved.
%% 
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%% 
%% %CopyrightEnd%
%%

%% There are some environment variables that can be used to "manipulate"
%% the test suite: 
%%
%% Variable that controls which 'groups' are to run (with default values)
%%
%%         ESOCK_TEST_API:         include
%%         ESOCK_TEST_SOCK_CLOSE:  include
%%         ESOCK_TEST_TRAFFIC:     include
%%         ESOCK_TEST_TTEST:       exclude
%%
%% Variable that controls "verbosity" of the test case(s):
%%
%%         ESOCK_TEST_QUIET: true (default) | false
%%
%% Defines the runtime of the ttest cases
%% (This is the time during which "measurement" is performed. 
%%  the actual time it takes for the test case to complete
%%  will be longer; setup, completion, ...)
%%
%%          ESOCK_TEST_TTEST_RUNTIME: 10 seconds
%%              Format of values: <integer>[<unit>]
%%              Where unit is: ms | s | m
%%                 ms - milli seconds
%%                 s  - seconds (default)
%%                 m  - minutes
%%

%% Run the entire test suite: 
%% ts:run(emulator, socket_SUITE, [batch]).
%%
%% Run a specific group:
%% ts:run(emulator, socket_SUITE, {group, foo}, [batch]).
%%
%% Run a specific test case:
%% ts:run(emulator, socket_SUITE, foo, [batch]).

-module(socket_SUITE).

-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").

%% Suite exports
-export([suite/0, all/0, groups/0]).
-export([init_per_suite/1,    end_per_suite/1,
         init_per_group/2,    end_per_group/2,
         init_per_testcase/2, end_per_testcase/2]).

%% Test cases
-export([
         %% *** API Misc ***
         api_m_debug/1,

         %% *** API Basic ***
         api_b_open_and_close_udp4/1,
         api_b_open_and_close_tcp4/1,
         api_b_open_and_close_udpL/1,
         api_b_open_and_close_tcpL/1,
         api_b_sendto_and_recvfrom_udp4/1,
         api_b_sendto_and_recvfrom_udpL/1,
         api_b_sendmsg_and_recvmsg_udp4/1,
         api_b_sendmsg_and_recvmsg_udpL/1,
         api_b_send_and_recv_tcp4/1,
         api_b_send_and_recv_tcpL/1,
         api_b_sendmsg_and_recvmsg_tcp4/1,
         api_b_sendmsg_and_recvmsg_tcpL/1,

         %% *** API async ***
         api_a_connect_tcp4/1,
         api_a_sendto_and_recvfrom_udp4/1,
         api_a_sendmsg_and_recvmsg_udp4/1,
         api_a_send_and_recv_tcp4/1,
         api_a_sendmsg_and_recvmsg_tcp4/1,
         api_a_recvfrom_cancel_udp4/1,
         api_a_recvmsg_cancel_udp4/1,
         api_a_accept_cancel_tcp4/1,
         api_a_recv_cancel_tcp4/1,
         api_a_recvmsg_cancel_tcp4/1,
         api_a_mrecvfrom_cancel_udp4/1,
         api_a_mrecvmsg_cancel_udp4/1,
         api_a_maccept_cancel_tcp4/1,
         api_a_mrecv_cancel_tcp4/1,
         api_a_mrecvmsg_cancel_tcp4/1,


         %% *** API Options ***
         api_opt_simple_otp_options/1,
         api_opt_simple_otp_rcvbuf_option/1,
         api_opt_simple_otp_controlling_process/1,
         api_opt_ip_add_drop_membership/1,

         %% *** API Operation Timeout ***
         api_to_connect_tcp4/1,
         api_to_connect_tcp6/1,
         api_to_accept_tcp4/1,
         api_to_accept_tcp6/1,
         api_to_maccept_tcp4/1,
         api_to_maccept_tcp6/1,
         api_to_send_tcp4/1,
         api_to_send_tcp6/1,
         api_to_sendto_udp4/1,
         api_to_sendto_udp6/1,
         api_to_sendmsg_tcp4/1,
         api_to_sendmsg_tcp6/1,
         api_to_recv_udp4/1,
         api_to_recv_udp6/1,
         api_to_recv_tcp4/1,
         api_to_recv_tcp6/1,
         api_to_recvfrom_udp4/1,
         api_to_recvfrom_udp6/1,
         api_to_recvmsg_udp4/1,
         api_to_recvmsg_udp6/1,
         api_to_recvmsg_tcp4/1,
         api_to_recvmsg_tcp6/1,

         %% *** Socket Closure ***
         sc_cpe_socket_cleanup_tcp4/1,
         sc_cpe_socket_cleanup_tcp6/1,
         sc_cpe_socket_cleanup_tcpL/1,
         sc_cpe_socket_cleanup_udp4/1,
         sc_cpe_socket_cleanup_udp6/1,
         sc_cpe_socket_cleanup_udpL/1,

         sc_lc_recv_response_tcp4/1,
         sc_lc_recv_response_tcp6/1,
         sc_lc_recv_response_tcpL/1,
         sc_lc_recvfrom_response_udp4/1,
         sc_lc_recvfrom_response_udp6/1,
         sc_lc_recvfrom_response_udpL/1,
         sc_lc_recvmsg_response_tcp4/1,
         sc_lc_recvmsg_response_tcp6/1,
         sc_lc_recvmsg_response_tcpL/1,
         sc_lc_recvmsg_response_udp4/1,
         sc_lc_recvmsg_response_udp6/1,
         sc_lc_recvmsg_response_udpL/1,
         sc_lc_acceptor_response_tcp4/1,
         sc_lc_acceptor_response_tcp6/1,
         sc_lc_acceptor_response_tcpL/1,

         sc_rc_recv_response_tcp4/1,
         sc_rc_recv_response_tcp6/1,
         sc_rc_recv_response_tcpL/1,
         sc_rc_recvmsg_response_tcp4/1,
         sc_rc_recvmsg_response_tcp6/1,
         sc_rc_recvmsg_response_tcpL/1,

         sc_rs_recv_send_shutdown_receive_tcp4/1,
         sc_rs_recv_send_shutdown_receive_tcp6/1,
         sc_rs_recv_send_shutdown_receive_tcpL/1,
         sc_rs_recvmsg_send_shutdown_receive_tcp4/1,
         sc_rs_recvmsg_send_shutdown_receive_tcp6/1,
         sc_rs_recvmsg_send_shutdown_receive_tcpL/1,

         %% *** Traffic ***
         traffic_send_and_recv_chunks_tcp4/1,
         traffic_send_and_recv_chunks_tcp6/1,
         traffic_send_and_recv_chunks_tcpL/1,

         traffic_ping_pong_small_send_and_recv_tcp4/1,
         traffic_ping_pong_small_send_and_recv_tcp6/1,
         traffic_ping_pong_small_send_and_recv_tcpL/1,
         traffic_ping_pong_medium_send_and_recv_tcp4/1,
         traffic_ping_pong_medium_send_and_recv_tcp6/1,
         traffic_ping_pong_medium_send_and_recv_tcpL/1,
         traffic_ping_pong_large_send_and_recv_tcp4/1,
         traffic_ping_pong_large_send_and_recv_tcp6/1,
         traffic_ping_pong_large_send_and_recv_tcpL/1,

         traffic_ping_pong_small_sendto_and_recvfrom_udp4/1,
         traffic_ping_pong_small_sendto_and_recvfrom_udp6/1,
         traffic_ping_pong_small_sendto_and_recvfrom_udpL/1,
         traffic_ping_pong_medium_sendto_and_recvfrom_udp4/1,
         traffic_ping_pong_medium_sendto_and_recvfrom_udp6/1,
         traffic_ping_pong_medium_sendto_and_recvfrom_udpL/1,

         traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4/1,
         traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6/1,
         traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL/1,
         traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4/1,
         traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6/1,
         traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL/1,
         traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4/1,
         traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6/1,
         traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL/1,

         traffic_ping_pong_small_sendmsg_and_recvmsg_udp4/1,
         traffic_ping_pong_small_sendmsg_and_recvmsg_udp6/1,
         traffic_ping_pong_small_sendmsg_and_recvmsg_udpL/1,
         traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4/1,
         traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6/1,
         traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL/1,

         %% *** Time Test ***
         %% Server: transport = gen_tcp, active = false
         %% Client: transport = gen_tcp
         ttest_sgenf_cgenf_small_tcp4/1,
         ttest_sgenf_cgenf_small_tcp6/1,
         ttest_sgenf_cgenf_medium_tcp4/1,
         ttest_sgenf_cgenf_medium_tcp6/1,
         ttest_sgenf_cgenf_large_tcp4/1,
         ttest_sgenf_cgenf_large_tcp6/1,

         ttest_sgenf_cgeno_small_tcp4/1,
         ttest_sgenf_cgeno_small_tcp6/1,
         ttest_sgenf_cgeno_medium_tcp4/1,
         ttest_sgenf_cgeno_medium_tcp6/1,
         ttest_sgenf_cgeno_large_tcp4/1,
         ttest_sgenf_cgeno_large_tcp6/1,

         ttest_sgenf_cgent_small_tcp4/1,
         ttest_sgenf_cgent_small_tcp6/1,
         ttest_sgenf_cgent_medium_tcp4/1,
         ttest_sgenf_cgent_medium_tcp6/1,
         ttest_sgenf_cgent_large_tcp4/1,
         ttest_sgenf_cgent_large_tcp6/1,

         %% Server: transport = gen_tcp, active = false
         %% Client: transport = socket(tcp)
         ttest_sgenf_csockf_small_tcp4/1,
         ttest_sgenf_csockf_small_tcp6/1,
         ttest_sgenf_csockf_medium_tcp4/1,
         ttest_sgenf_csockf_medium_tcp6/1,
         ttest_sgenf_csockf_large_tcp4/1,
         ttest_sgenf_csockf_large_tcp6/1,

         ttest_sgenf_csocko_small_tcp4/1,
         ttest_sgenf_csocko_small_tcp6/1,
         ttest_sgenf_csocko_medium_tcp4/1,
         ttest_sgenf_csocko_medium_tcp6/1,
         ttest_sgenf_csocko_large_tcp4/1,
         ttest_sgenf_csocko_large_tcp6/1,

         ttest_sgenf_csockt_small_tcp4/1,
         ttest_sgenf_csockt_small_tcp6/1,
         ttest_sgenf_csockt_medium_tcp4/1,
         ttest_sgenf_csockt_medium_tcp6/1,
         ttest_sgenf_csockt_large_tcp4/1,
         ttest_sgenf_csockt_large_tcp6/1,

         %% Server: transport = gen_tcp, active = once
         %% Client: transport = gen_tcp
         ttest_sgeno_cgenf_small_tcp4/1,
         ttest_sgeno_cgenf_small_tcp6/1,
         ttest_sgeno_cgenf_medium_tcp4/1,
         ttest_sgeno_cgenf_medium_tcp6/1,
         ttest_sgeno_cgenf_large_tcp4/1,
         ttest_sgeno_cgenf_large_tcp6/1,

         ttest_sgeno_cgeno_small_tcp4/1,
         ttest_sgeno_cgeno_small_tcp6/1,
         ttest_sgeno_cgeno_medium_tcp4/1,
         ttest_sgeno_cgeno_medium_tcp6/1,
         ttest_sgeno_cgeno_large_tcp4/1,
         ttest_sgeno_cgeno_large_tcp6/1,

         ttest_sgeno_cgent_small_tcp4/1,
         ttest_sgeno_cgent_small_tcp6/1,
         ttest_sgeno_cgent_medium_tcp4/1,
         ttest_sgeno_cgent_medium_tcp6/1,
         ttest_sgeno_cgent_large_tcp4/1,
         ttest_sgeno_cgent_large_tcp6/1,

         %% Server: transport = gen_tcp, active = once
         %% Client: transport = socket(tcp)
         ttest_sgeno_csockf_small_tcp4/1,
         ttest_sgeno_csockf_small_tcp6/1,
         ttest_sgeno_csockf_medium_tcp4/1,
         ttest_sgeno_csockf_medium_tcp6/1,
         ttest_sgeno_csockf_large_tcp4/1,
         ttest_sgeno_csockf_large_tcp6/1,

         ttest_sgeno_csocko_small_tcp4/1,
         ttest_sgeno_csocko_small_tcp6/1,
         ttest_sgeno_csocko_medium_tcp4/1,
         ttest_sgeno_csocko_medium_tcp6/1,
         ttest_sgeno_csocko_large_tcp4/1,
         ttest_sgeno_csocko_large_tcp6/1,

         ttest_sgeno_csockt_small_tcp4/1,
         ttest_sgeno_csockt_small_tcp6/1,
         ttest_sgeno_csockt_medium_tcp4/1,
         ttest_sgeno_csockt_medium_tcp6/1,
         ttest_sgeno_csockt_large_tcp4/1,
         ttest_sgeno_csockt_large_tcp6/1,

         %% Server: transport = gen_tcp, active = true
         %% Client: transport = gen_tcp
         ttest_sgent_cgenf_small_tcp4/1,
         ttest_sgent_cgenf_small_tcp6/1,
         ttest_sgent_cgenf_medium_tcp4/1,
         ttest_sgent_cgenf_medium_tcp6/1,
         ttest_sgent_cgenf_large_tcp4/1,
         ttest_sgent_cgenf_large_tcp6/1,

         ttest_sgent_cgeno_small_tcp4/1,
         ttest_sgent_cgeno_small_tcp6/1,
         ttest_sgent_cgeno_medium_tcp4/1,
         ttest_sgent_cgeno_medium_tcp6/1,
         ttest_sgent_cgeno_large_tcp4/1,
         ttest_sgent_cgeno_large_tcp6/1,

         ttest_sgent_cgent_small_tcp4/1,
         ttest_sgent_cgent_small_tcp6/1,
         ttest_sgent_cgent_medium_tcp4/1,
         ttest_sgent_cgent_medium_tcp6/1,
         ttest_sgent_cgent_large_tcp4/1,
         ttest_sgent_cgent_large_tcp6/1,

         %% Server: transport = gen_tcp, active = true
         %% Client: transport = socket(tcp)
         ttest_sgent_csockf_small_tcp4/1,
         ttest_sgent_csockf_small_tcp6/1,
         ttest_sgent_csockf_medium_tcp4/1,
         ttest_sgent_csockf_medium_tcp6/1,
         ttest_sgent_csockf_large_tcp4/1,
         ttest_sgent_csockf_large_tcp6/1,

         ttest_sgent_csocko_small_tcp4/1,
         ttest_sgent_csocko_small_tcp6/1,
         ttest_sgent_csocko_medium_tcp4/1,
         ttest_sgent_csocko_medium_tcp6/1,
         ttest_sgent_csocko_large_tcp4/1,
         ttest_sgent_csocko_large_tcp6/1,

         ttest_sgent_csockt_small_tcp4/1,
         ttest_sgent_csockt_small_tcp6/1,
         ttest_sgent_csockt_medium_tcp4/1,
         ttest_sgent_csockt_medium_tcp6/1,
         ttest_sgent_csockt_large_tcp4/1,
         ttest_sgent_csockt_large_tcp6/1,

         %% Server: transport = socket(tcp), active = false
         %% Client: transport = gen_tcp
         ttest_ssockf_cgenf_small_tcp4/1,
         ttest_ssockf_cgenf_small_tcp6/1,
         ttest_ssockf_cgenf_medium_tcp4/1,
         ttest_ssockf_cgenf_medium_tcp6/1,
         ttest_ssockf_cgenf_large_tcp4/1,
         ttest_ssockf_cgenf_large_tcp6/1,

         ttest_ssockf_cgeno_small_tcp4/1,
         ttest_ssockf_cgeno_small_tcp6/1,
         ttest_ssockf_cgeno_medium_tcp4/1,
         ttest_ssockf_cgeno_medium_tcp6/1,
         ttest_ssockf_cgeno_large_tcp4/1,
         ttest_ssockf_cgeno_large_tcp6/1,

         ttest_ssockf_cgent_small_tcp4/1,
         ttest_ssockf_cgent_small_tcp6/1,
         ttest_ssockf_cgent_medium_tcp4/1,
         ttest_ssockf_cgent_medium_tcp6/1,
         ttest_ssockf_cgent_large_tcp4/1,
         ttest_ssockf_cgent_large_tcp6/1,

         %% Server: transport = socket(tcp), active = false
         %% Client: transport = socket(tcp)
         ttest_ssockf_csockf_small_tcp4/1,
         ttest_ssockf_csockf_small_tcp6/1,
         ttest_ssockf_csockf_small_tcpL/1,
         ttest_ssockf_csockf_medium_tcp4/1,
         ttest_ssockf_csockf_medium_tcp6/1,
         ttest_ssockf_csockf_medium_tcpL/1,
         ttest_ssockf_csockf_large_tcp4/1,
         ttest_ssockf_csockf_large_tcp6/1,
         ttest_ssockf_csockf_large_tcpL/1,

         ttest_ssockf_csocko_small_tcp4/1,
         ttest_ssockf_csocko_small_tcp6/1,
         ttest_ssockf_csocko_small_tcpL/1,
         ttest_ssockf_csocko_medium_tcp4/1,
         ttest_ssockf_csocko_medium_tcp6/1,
         ttest_ssockf_csocko_medium_tcpL/1,
         ttest_ssockf_csocko_large_tcp4/1,
         ttest_ssockf_csocko_large_tcp6/1,
         ttest_ssockf_csocko_large_tcpL/1,

         ttest_ssockf_csockt_small_tcp4/1,
         ttest_ssockf_csockt_small_tcp6/1,
         ttest_ssockf_csockt_small_tcpL/1,
         ttest_ssockf_csockt_medium_tcp4/1,
         ttest_ssockf_csockt_medium_tcp6/1,
         ttest_ssockf_csockt_medium_tcpL/1,
         ttest_ssockf_csockt_large_tcp4/1,
         ttest_ssockf_csockt_large_tcp6/1,
         ttest_ssockf_csockt_large_tcpL/1,

         %% Server: transport = socket(tcp), active = once
         %% Client: transport = gen_tcp
         ttest_ssocko_cgenf_small_tcp4/1,
         ttest_ssocko_cgenf_small_tcp6/1,
         ttest_ssocko_cgenf_medium_tcp4/1,
         ttest_ssocko_cgenf_medium_tcp6/1,
         ttest_ssocko_cgenf_large_tcp4/1,
         ttest_ssocko_cgenf_large_tcp6/1,

         ttest_ssocko_cgeno_small_tcp4/1,
         ttest_ssocko_cgeno_small_tcp6/1,
         ttest_ssocko_cgeno_medium_tcp4/1,
         ttest_ssocko_cgeno_medium_tcp6/1,
         ttest_ssocko_cgeno_large_tcp4/1,
         ttest_ssocko_cgeno_large_tcp6/1,

         ttest_ssocko_cgent_small_tcp4/1,
         ttest_ssocko_cgent_small_tcp6/1,
         ttest_ssocko_cgent_medium_tcp4/1,
         ttest_ssocko_cgent_medium_tcp6/1,
         ttest_ssocko_cgent_large_tcp4/1,
         ttest_ssocko_cgent_large_tcp6/1,

         %% Server: transport = socket(tcp), active = once
         %% Client: transport = socket(tcp)
         ttest_ssocko_csockf_small_tcp4/1,
         ttest_ssocko_csockf_small_tcp6/1,
         ttest_ssocko_csockf_small_tcpL/1,
         ttest_ssocko_csockf_medium_tcp4/1,
         ttest_ssocko_csockf_medium_tcpL/1,
         ttest_ssocko_csockf_medium_tcp6/1,
         ttest_ssocko_csockf_large_tcp4/1,
         ttest_ssocko_csockf_large_tcp6/1,
         ttest_ssocko_csockf_large_tcpL/1,

         ttest_ssocko_csocko_small_tcp4/1,
         ttest_ssocko_csocko_small_tcp6/1,
         ttest_ssocko_csocko_small_tcpL/1,
         ttest_ssocko_csocko_medium_tcp4/1,
         ttest_ssocko_csocko_medium_tcp6/1,
         ttest_ssocko_csocko_medium_tcpL/1,
         ttest_ssocko_csocko_large_tcp4/1,
         ttest_ssocko_csocko_large_tcp6/1,
         ttest_ssocko_csocko_large_tcpL/1,

         ttest_ssocko_csockt_small_tcp4/1,
         ttest_ssocko_csockt_small_tcp6/1,
         ttest_ssocko_csockt_small_tcpL/1,
         ttest_ssocko_csockt_medium_tcp4/1,
         ttest_ssocko_csockt_medium_tcp6/1,
         ttest_ssocko_csockt_medium_tcpL/1,
         ttest_ssocko_csockt_large_tcp4/1,
         ttest_ssocko_csockt_large_tcp6/1,
         ttest_ssocko_csockt_large_tcpL/1,

         %% Server: transport = socket(tcp), active = true
         %% Client: transport = gen_tcp
         ttest_ssockt_cgenf_small_tcp4/1,
         ttest_ssockt_cgenf_small_tcp6/1,
         ttest_ssockt_cgenf_medium_tcp4/1,
         ttest_ssockt_cgenf_medium_tcp6/1,
         ttest_ssockt_cgenf_large_tcp4/1,
         ttest_ssockt_cgenf_large_tcp6/1,

         ttest_ssockt_cgeno_small_tcp4/1,
         ttest_ssockt_cgeno_small_tcp6/1,
         ttest_ssockt_cgeno_medium_tcp4/1,
         ttest_ssockt_cgeno_medium_tcp6/1,
         ttest_ssockt_cgeno_large_tcp4/1,
         ttest_ssockt_cgeno_large_tcp6/1,

         ttest_ssockt_cgent_small_tcp4/1,
         ttest_ssockt_cgent_small_tcp6/1,
         ttest_ssockt_cgent_medium_tcp4/1,
         ttest_ssockt_cgent_medium_tcp6/1,
         ttest_ssockt_cgent_large_tcp4/1,
         ttest_ssockt_cgent_large_tcp6/1,

         %% Server: transport = socket(tcp), active = true
         %% Client: transport = socket(tcp)
         ttest_ssockt_csockf_small_tcp4/1,
         ttest_ssockt_csockf_small_tcp6/1,
         ttest_ssockt_csockf_small_tcpL/1,
         ttest_ssockt_csockf_medium_tcp4/1,
         ttest_ssockt_csockf_medium_tcp6/1,
         ttest_ssockt_csockf_medium_tcpL/1,
         ttest_ssockt_csockf_large_tcp4/1,
         ttest_ssockt_csockf_large_tcp6/1,
         ttest_ssockt_csockf_large_tcpL/1,

         ttest_ssockt_csocko_small_tcp4/1,
         ttest_ssockt_csocko_small_tcp6/1,
         ttest_ssockt_csocko_small_tcpL/1,
         ttest_ssockt_csocko_medium_tcp4/1,
         ttest_ssockt_csocko_medium_tcp6/1,
         ttest_ssockt_csocko_medium_tcpL/1,
         ttest_ssockt_csocko_large_tcp4/1,
         ttest_ssockt_csocko_large_tcp6/1,
         ttest_ssockt_csocko_large_tcpL/1,

         ttest_ssockt_csockt_small_tcp4/1,
         ttest_ssockt_csockt_small_tcp6/1,
         ttest_ssockt_csockt_small_tcpL/1,
         ttest_ssockt_csockt_medium_tcp4/1,
         ttest_ssockt_csockt_medium_tcp6/1,
         ttest_ssockt_csockt_medium_tcpL/1,
         ttest_ssockt_csockt_large_tcp4/1,
         ttest_ssockt_csockt_large_tcp6/1,
         ttest_ssockt_csockt_large_tcpL/1

         %% Tickets
        ]).


-include("socket_test_evaluator.hrl").

%% Internal exports
%% -export([]).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-define(BASIC_REQ, <<"hejsan">>).
-define(BASIC_REP, <<"hoppsan">>).

-define(DATA,      <<"HOPPSAN">>). % Temporary
-define(FAIL(R), exit(R)).

-define(SLEEP(T), receive after T -> ok end).

-define(MINS(M), timer:minutes(M)).
-define(SECS(S), timer:seconds(S)).

-define(TT(T),   ct:timetrap(T)).

-define(LIB,       socket_test_lib).
-define(TTEST_LIB, socket_test_ttest_lib).
-define(LOGGER,    socket_test_logger).

-define(TPP_SMALL,  lists:seq(1, 8)).
-define(TPP_MEDIUM, lists:flatten(lists:duplicate(1024, ?TPP_SMALL))).
-define(TPP_LARGE,  lists:flatten(lists:duplicate(1024, ?TPP_MEDIUM))).

-define(TPP_SMALL_NUM,  10000).
-define(TPP_MEDIUM_NUM, 1000).
-define(TPP_LARGE_NUM,  100).

-define(TTEST_RUNTIME,  ?SECS(10)).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

suite() ->
    [{ct_hooks,[ts_install_cth]},
     {timetrap,{minutes,1}}].

all() -> 
    Groups = [{api,            "ESOCK_TEST_API",        include},
	      {socket_closure, "ESOCK_TEST_SOCK_CLOSE", include},
	      {traffic,        "ESOCK_TEST_TRAFFIC",    include},
	      {ttest,          "ESOCK_TEST_TTEST",      exclude}],
    [use_group(Group, Env, Default) || {Group, Env, Default} <- Groups].

use_group(Group, Env, Default) ->
	case os:getenv(Env) of
	    false when (Default =:= include) ->
		[{group, Group}];
	    false ->
		[];
	    Val ->
		case list_to_atom(string:to_lower(Val)) of
		    Use when (Use =:= include) orelse 
			     (Use =:= enable) orelse 
			     (Use =:= true) ->
			[{group, Group}];
		    _ ->
			[]
		end
	end.
    

groups() -> 
    [{api,                        [], api_cases()},
     {api_misc,                   [], api_misc_cases()},
     {api_basic,                  [], api_basic_cases()},
     {api_async,                  [], api_async_cases()},
     {api_options,                [], api_options_cases()},
     {api_options_otp,            [], api_options_otp_cases()},
     {api_options_ip,             [], api_options_ip_cases()},
     {api_op_with_timeout,        [], api_op_with_timeout_cases()},
     {socket_closure,             [], socket_closure_cases()},
     {sc_ctrl_proc_exit,          [], sc_cp_exit_cases()},
     {sc_local_close,             [], sc_lc_cases()},
     {sc_remote_close,            [], sc_rc_cases()},
     {sc_remote_shutdown,         [], sc_rs_cases()},
     {traffic,                    [], traffic_cases()},
     {traffic_chunks,             [], traffic_chunks_cases()},
     {traffic_pp_send_recv,       [], traffic_pp_send_recv_cases()},
     {traffic_pp_sendto_recvfrom, [], traffic_pp_sendto_recvfrom_cases()},
     {traffic_pp_sendmsg_recvmsg, [], traffic_pp_sendmsg_recvmsg_cases()},
     {ttest,                      [], ttest_cases()},
     {ttest_sgenf,                [], ttest_sgenf_cases()},
     {ttest_sgenf_cgen,           [], ttest_sgenf_cgen_cases()},
     {ttest_sgenf_cgenf,          [], ttest_sgenf_cgenf_cases()},
     {ttest_sgenf_cgeno,          [], ttest_sgenf_cgeno_cases()},
     {ttest_sgenf_cgent,          [], ttest_sgenf_cgent_cases()},
     {ttest_sgenf_csock,          [], ttest_sgenf_csock_cases()},
     {ttest_sgenf_csockf,         [], ttest_sgenf_csockf_cases()},
     {ttest_sgenf_csocko,         [], ttest_sgenf_csocko_cases()},
     {ttest_sgenf_csockt,         [], ttest_sgenf_csockt_cases()},
     {ttest_sgeno,                [], ttest_sgeno_cases()},
     {ttest_sgeno_cgen,           [], ttest_sgeno_cgen_cases()},
     {ttest_sgeno_cgenf,          [], ttest_sgeno_cgenf_cases()},
     {ttest_sgeno_cgeno,          [], ttest_sgeno_cgeno_cases()},
     {ttest_sgeno_cgent,          [], ttest_sgeno_cgent_cases()},
     {ttest_sgeno_csock,          [], ttest_sgeno_csock_cases()},
     {ttest_sgeno_csockf,         [], ttest_sgeno_csockf_cases()},
     {ttest_sgeno_csocko,         [], ttest_sgeno_csocko_cases()},
     {ttest_sgeno_csockt,         [], ttest_sgeno_csockt_cases()},
     {ttest_sgent,                [], ttest_sgent_cases()},
     {ttest_sgent_cgen,           [], ttest_sgent_cgen_cases()},
     {ttest_sgent_cgenf,          [], ttest_sgent_cgenf_cases()},
     {ttest_sgent_cgeno,          [], ttest_sgent_cgeno_cases()},
     {ttest_sgent_cgent,          [], ttest_sgent_cgent_cases()},
     {ttest_sgent_csock,          [], ttest_sgent_csock_cases()},
     {ttest_sgent_csockf,         [], ttest_sgent_csockf_cases()},
     {ttest_sgent_csocko,         [], ttest_sgent_csocko_cases()},
     {ttest_sgent_csockt,         [], ttest_sgent_csockt_cases()},
     {ttest_ssockf,               [], ttest_ssockf_cases()},
     {ttest_ssockf_cgen,          [], ttest_ssockf_cgen_cases()},
     {ttest_ssockf_cgenf,         [], ttest_ssockf_cgenf_cases()},
     {ttest_ssockf_cgeno,         [], ttest_ssockf_cgeno_cases()},
     {ttest_ssockf_cgent,         [], ttest_ssockf_cgent_cases()},
     {ttest_ssockf_csock,         [], ttest_ssockf_csock_cases()},
     {ttest_ssockf_csockf,        [], ttest_ssockf_csockf_cases()},
     {ttest_ssockf_csocko,        [], ttest_ssockf_csocko_cases()},
     {ttest_ssockf_csockt,        [], ttest_ssockf_csockt_cases()},
     {ttest_ssocko,               [], ttest_ssocko_cases()},
     {ttest_ssocko_cgen,          [], ttest_ssocko_cgen_cases()},
     {ttest_ssocko_cgenf,         [], ttest_ssocko_cgenf_cases()},
     {ttest_ssocko_cgeno,         [], ttest_ssocko_cgeno_cases()},
     {ttest_ssocko_cgent,         [], ttest_ssocko_cgent_cases()},
     {ttest_ssocko_csock,         [], ttest_ssocko_csock_cases()},
     {ttest_ssocko_csockf,        [], ttest_ssocko_csockf_cases()},
     {ttest_ssocko_csocko,        [], ttest_ssocko_csocko_cases()},
     {ttest_ssocko_csockt,        [], ttest_ssocko_csockt_cases()},
     {ttest_ssockt,               [], ttest_ssockt_cases()},
     {ttest_ssockt_cgen,          [], ttest_ssockt_cgen_cases()},
     {ttest_ssockt_cgenf,         [], ttest_ssockt_cgenf_cases()},
     {ttest_ssockt_cgeno,         [], ttest_ssockt_cgeno_cases()},
     {ttest_ssockt_cgent,         [], ttest_ssockt_cgent_cases()},
     {ttest_ssockt_csock,         [], ttest_ssockt_csock_cases()},
     {ttest_ssockt_csockf,        [], ttest_ssockt_csockf_cases()},
     {ttest_ssockt_csocko,        [], ttest_ssockt_csocko_cases()},
     {ttest_ssockt_csockt,        [], ttest_ssockt_csockt_cases()}

     %% {tickets,             [], ticket_cases()}
    ].
     
api_cases() ->
    [
     {group, api_misc},
     {group, api_basic},
     {group, api_async},
     {group, api_options},
     {group, api_op_with_timeout}
    ].

api_misc_cases() ->
    [
     api_m_debug
    ].

api_basic_cases() ->
    [
     api_b_open_and_close_udp4,
     api_b_open_and_close_tcp4,
     api_b_open_and_close_udpL,
     api_b_open_and_close_tcpL,
     api_b_sendto_and_recvfrom_udp4,
     api_b_sendto_and_recvfrom_udpL,
     api_b_sendmsg_and_recvmsg_udp4,
     api_b_sendmsg_and_recvmsg_udpL,
     api_b_send_and_recv_tcp4,
     api_b_send_and_recv_tcpL,
     api_b_sendmsg_and_recvmsg_tcp4,
     api_b_sendmsg_and_recvmsg_tcpL
    ].

api_async_cases() ->
    [
     api_a_connect_tcp4,
     api_a_sendto_and_recvfrom_udp4,
     api_a_sendmsg_and_recvmsg_udp4,
     api_a_send_and_recv_tcp4,
     api_a_sendmsg_and_recvmsg_tcp4,
     api_a_recvfrom_cancel_udp4,
     api_a_recvmsg_cancel_udp4,
     api_a_accept_cancel_tcp4,
     api_a_recv_cancel_tcp4,
     api_a_recvmsg_cancel_tcp4,
     api_a_mrecvfrom_cancel_udp4,
     api_a_mrecvmsg_cancel_udp4,
     api_a_maccept_cancel_tcp4,
     api_a_mrecv_cancel_tcp4,
     api_a_mrecvmsg_cancel_tcp4
    ].

api_options_cases() ->
    [
     {group, api_options_otp},
     {group, api_options_ip}
    ].

api_options_otp_cases() ->
    [
     api_opt_simple_otp_options,
     api_opt_simple_otp_rcvbuf_option,
     api_opt_simple_otp_controlling_process
    ].

api_options_ip_cases() ->
    [
     api_opt_ip_add_drop_membership
    ].

api_op_with_timeout_cases() ->
    [
     api_to_connect_tcp4,
     api_to_connect_tcp6,
     api_to_accept_tcp4,
     api_to_accept_tcp6,
     api_to_maccept_tcp4,
     api_to_maccept_tcp6,
     api_to_send_tcp4,
     api_to_send_tcp6,
     api_to_sendto_udp4,
     api_to_sendto_udp6,
     api_to_sendmsg_tcp4,
     api_to_sendmsg_tcp6,
     api_to_recv_udp4,
     api_to_recv_udp6,
     api_to_recv_tcp4,
     api_to_recv_tcp6,
     api_to_recvfrom_udp4,
     api_to_recvfrom_udp6,
     api_to_recvmsg_udp4,
     api_to_recvmsg_udp6,
     api_to_recvmsg_tcp4,
     api_to_recvmsg_tcp6
    ].

%% These cases tests what happens when the socket is closed/shutdown,
%% locally or remotely.
socket_closure_cases() ->
    [
     {group, sc_ctrl_proc_exit},
     {group, sc_local_close},
     {group, sc_remote_close},
     {group, sc_remote_shutdown}
    ].

%% These cases are all about socket cleanup after the controlling process
%% exits *without* explicitly calling socket:close/1.
sc_cp_exit_cases() ->
    [
     sc_cpe_socket_cleanup_tcp4,
     sc_cpe_socket_cleanup_tcp6,
     sc_cpe_socket_cleanup_tcpL,
     sc_cpe_socket_cleanup_udp4,
     sc_cpe_socket_cleanup_udp6,
     sc_cpe_socket_cleanup_udpL
    ].

%% These cases tests what happens when the socket is closed locally.
sc_lc_cases() ->
    [
     sc_lc_recv_response_tcp4,
     sc_lc_recv_response_tcp6,
     sc_lc_recv_response_tcpL,

     sc_lc_recvfrom_response_udp4,
     sc_lc_recvfrom_response_udp6,
     sc_lc_recvfrom_response_udpL,

     sc_lc_recvmsg_response_tcp4,
     sc_lc_recvmsg_response_tcp6,
     sc_lc_recvmsg_response_tcpL,
     sc_lc_recvmsg_response_udp4,
     sc_lc_recvmsg_response_udp6,
     sc_lc_recvmsg_response_udpL,

     sc_lc_acceptor_response_tcp4,
     sc_lc_acceptor_response_tcp6,
     sc_lc_acceptor_response_tcpL
    ].

%% These cases tests what happens when the socket is closed remotely.
sc_rc_cases() ->
    [
     sc_rc_recv_response_tcp4,
     sc_rc_recv_response_tcp6,
     sc_rc_recv_response_tcpL,

     sc_rc_recvmsg_response_tcp4,
     sc_rc_recvmsg_response_tcp6,
     sc_rc_recvmsg_response_tcpL
    ].

%% These cases tests what happens when the socket is shutdown/closed remotely
%% after writing and reading is ongoing.
sc_rs_cases() ->
    [
     sc_rs_recv_send_shutdown_receive_tcp4,
     sc_rs_recv_send_shutdown_receive_tcp6,
     sc_rs_recv_send_shutdown_receive_tcpL,

     sc_rs_recvmsg_send_shutdown_receive_tcp4,
     sc_rs_recvmsg_send_shutdown_receive_tcp6,
     sc_rs_recvmsg_send_shutdown_receive_tcpL
    ].


traffic_cases() ->
    [
     {group, traffic_chunks},
     {group, traffic_pp_send_recv},
     {group, traffic_pp_sendto_recvfrom},
     {group, traffic_pp_sendmsg_recvmsg}
    ].

traffic_chunks_cases() ->
    [
     traffic_send_and_recv_chunks_tcp4,
     traffic_send_and_recv_chunks_tcp6,
     traffic_send_and_recv_chunks_tcpL
    ].

traffic_pp_send_recv_cases() ->
    [
     traffic_ping_pong_small_send_and_recv_tcp4,
     traffic_ping_pong_small_send_and_recv_tcp6,
     traffic_ping_pong_small_send_and_recv_tcpL,
     traffic_ping_pong_medium_send_and_recv_tcp4,
     traffic_ping_pong_medium_send_and_recv_tcp6,
     traffic_ping_pong_medium_send_and_recv_tcpL,
     traffic_ping_pong_large_send_and_recv_tcp4,
     traffic_ping_pong_large_send_and_recv_tcp6,
     traffic_ping_pong_large_send_and_recv_tcpL
    ].    

traffic_pp_sendto_recvfrom_cases() ->
    [
     traffic_ping_pong_small_sendto_and_recvfrom_udp4,
     traffic_ping_pong_small_sendto_and_recvfrom_udp6,
     traffic_ping_pong_small_sendto_and_recvfrom_udpL,
     traffic_ping_pong_medium_sendto_and_recvfrom_udp4,
     traffic_ping_pong_medium_sendto_and_recvfrom_udp6,
     traffic_ping_pong_medium_sendto_and_recvfrom_udpL
    ].

traffic_pp_sendmsg_recvmsg_cases() ->
    [    
     traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4,
     traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6,
     traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL,
     traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4,
     traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6,
     traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL,
     traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4,
     traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6,
     traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL,

     traffic_ping_pong_small_sendmsg_and_recvmsg_udp4,
     traffic_ping_pong_small_sendmsg_and_recvmsg_udp6,
     traffic_ping_pong_small_sendmsg_and_recvmsg_udpL,
     traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4,
     traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6,
     traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL
    ].
    
ttest_cases() ->
    [
     %% Server: transport = gen_tcp, active = false
     {group, ttest_sgenf},

     %% Server: transport = gen_tcp, active = once
     {group, ttest_sgeno},

     %% Server: transport = gen_tcp, active = true
     {group, ttest_sgent},

     %% Server: transport = socket(tcp), active = false
     {group, ttest_ssockf},

     %% Server: transport = socket(tcp), active = once
     {group, ttest_ssocko},

     %% Server: transport = socket(tcp), active = true
     {group, ttest_ssockt}

    ].


%% Server: transport = gen_tcp, active = false
ttest_sgenf_cases() ->
    [
     {group, ttest_sgenf_cgen},
     {group, ttest_sgenf_csock}
    ].

%% Server: transport = gen_tcp, active = false
%% Client: transport = gen_tcp
ttest_sgenf_cgen_cases() ->
    [
     {group, ttest_sgenf_cgenf},
     {group, ttest_sgenf_cgeno},
     {group, ttest_sgenf_cgent}
    ].

%% Server: transport = gen_tcp, active = false
%% Client: transport = gen_tcp, active = false
ttest_sgenf_cgenf_cases() ->
    [
     ttest_sgenf_cgenf_small_tcp4,
     ttest_sgenf_cgenf_small_tcp6,

     ttest_sgenf_cgenf_medium_tcp4,
     ttest_sgenf_cgenf_medium_tcp6,

     ttest_sgenf_cgenf_large_tcp4,
     ttest_sgenf_cgenf_large_tcp6
    ].

%% Server: transport = gen_tcp, active = false
%% Client: transport = gen_tcp, active = once
ttest_sgenf_cgeno_cases() ->
    [
     ttest_sgenf_cgeno_small_tcp4,
     ttest_sgenf_cgeno_small_tcp6,

     ttest_sgenf_cgeno_medium_tcp4,
     ttest_sgenf_cgeno_medium_tcp6,

     ttest_sgenf_cgeno_large_tcp4,
     ttest_sgenf_cgeno_large_tcp6
    ].

%% Server: transport = gen_tcp, active = false
%% Client: transport = gen_tcp, active = true
ttest_sgenf_cgent_cases() ->
    [
     ttest_sgenf_cgent_small_tcp4,
     ttest_sgenf_cgent_small_tcp6,

     ttest_sgenf_cgent_medium_tcp4,
     ttest_sgenf_cgent_medium_tcp6,

     ttest_sgenf_cgent_large_tcp4,
     ttest_sgenf_cgent_large_tcp6
    ].

%% Server: transport = gen_tcp, active = false
%% Client: transport = socket(tcp)
ttest_sgenf_csock_cases() ->
    [
     {group, ttest_sgenf_csockf},
     {group, ttest_sgenf_csocko},
     {group, ttest_sgenf_csockt}
    ].

ttest_sgenf_csockf_cases() ->
    [
     ttest_sgenf_csockf_small_tcp4,
     ttest_sgenf_csockf_small_tcp6,

     ttest_sgenf_csockf_medium_tcp4,
     ttest_sgenf_csockf_medium_tcp6,

     ttest_sgenf_csockf_large_tcp4,
     ttest_sgenf_csockf_large_tcp6
    ].

ttest_sgenf_csocko_cases() ->
    [
     ttest_sgenf_csocko_small_tcp4,
     ttest_sgenf_csocko_small_tcp6,

     ttest_sgenf_csocko_medium_tcp4,
     ttest_sgenf_csocko_medium_tcp6,

     ttest_sgenf_csocko_large_tcp4,
     ttest_sgenf_csocko_large_tcp6
    ].

ttest_sgenf_csockt_cases() ->
    [
     ttest_sgenf_csockt_small_tcp4,
     ttest_sgenf_csockt_small_tcp6,

     ttest_sgenf_csockt_medium_tcp4,
     ttest_sgenf_csockt_medium_tcp6,

     ttest_sgenf_csockt_large_tcp4,
     ttest_sgenf_csockt_large_tcp6
    ].

%% Server: transport = gen_tcp, active = once
ttest_sgeno_cases() ->
    [
     {group, ttest_sgeno_cgen},
     {group, ttest_sgeno_csock}
    ].

%% Server: transport = gen_tcp, active = once
%% Client: transport = gen_tcp
ttest_sgeno_cgen_cases() ->
    [
     {group, ttest_sgeno_cgenf},
     {group, ttest_sgeno_cgeno},
     {group, ttest_sgeno_cgent}
    ].

%% Server: transport = gen_tcp, active = once
%% Client: transport = gen_tcp, active = false
ttest_sgeno_cgenf_cases() ->
    [
     ttest_sgeno_cgenf_small_tcp4,
     ttest_sgeno_cgenf_small_tcp6,

     ttest_sgeno_cgenf_medium_tcp4,
     ttest_sgeno_cgenf_medium_tcp6,

     ttest_sgeno_cgenf_large_tcp4,
     ttest_sgeno_cgenf_large_tcp6
    ].

%% Server: transport = gen_tcp, active = once
%% Client: transport = gen_tcp, active = once
ttest_sgeno_cgeno_cases() ->
    [
     ttest_sgeno_cgeno_small_tcp4,
     ttest_sgeno_cgeno_small_tcp6,

     ttest_sgeno_cgeno_medium_tcp4,
     ttest_sgeno_cgeno_medium_tcp6,

     ttest_sgeno_cgeno_large_tcp4,
     ttest_sgeno_cgeno_large_tcp6
    ].

%% Server: transport = gen_tcp, active = once
%% Client: transport = gen_tcp, active = true
ttest_sgeno_cgent_cases() ->
    [
     ttest_sgeno_cgent_small_tcp4,
     ttest_sgeno_cgent_small_tcp6,

     ttest_sgeno_cgent_medium_tcp4,
     ttest_sgeno_cgent_medium_tcp6,

     ttest_sgeno_cgent_large_tcp4,
     ttest_sgeno_cgent_large_tcp6
    ].

%% Server: transport = gen_tcp, active = once
%% Client: transport = socket(tcp)
ttest_sgeno_csock_cases() ->
    [
     {group, ttest_sgeno_csockf},
     {group, ttest_sgeno_csocko},
     {group, ttest_sgeno_csockt}
    ].

ttest_sgeno_csockf_cases() ->
    [
     ttest_sgeno_csockf_small_tcp4,
     ttest_sgeno_csockf_small_tcp6,

     ttest_sgeno_csockf_medium_tcp4,
     ttest_sgeno_csockf_medium_tcp6,

     ttest_sgeno_csockf_large_tcp4,
     ttest_sgeno_csockf_large_tcp6
    ].

ttest_sgeno_csocko_cases() ->
    [
     ttest_sgeno_csocko_small_tcp4,
     ttest_sgeno_csocko_small_tcp6,

     ttest_sgeno_csocko_medium_tcp4,
     ttest_sgeno_csocko_medium_tcp6,

     ttest_sgeno_csocko_large_tcp4,
     ttest_sgeno_csocko_large_tcp6
    ].

ttest_sgeno_csockt_cases() ->
    [
     ttest_sgeno_csockt_small_tcp4,
     ttest_sgeno_csockt_small_tcp6,

     ttest_sgeno_csockt_medium_tcp4,
     ttest_sgeno_csockt_medium_tcp6,

     ttest_sgeno_csockt_large_tcp4,
     ttest_sgeno_csockt_large_tcp6
    ].

%% Server: transport = gen_tcp, active = true
ttest_sgent_cases() ->
    [
     {group, ttest_sgent_cgen},
     {group, ttest_sgent_csock}
    ].

%% Server: transport = gen_tcp, active = true
%% Client: transport = gen_tcp
ttest_sgent_cgen_cases() ->
    [
     {group, ttest_sgent_cgenf},
     {group, ttest_sgent_cgeno},
     {group, ttest_sgent_cgent}
    ].

%% Server: transport = gen_tcp, active = true
%% Client: transport = gen_tcp, active = false
ttest_sgent_cgenf_cases() ->
    [
     ttest_sgent_cgenf_small_tcp4,
     ttest_sgent_cgenf_small_tcp6,

     ttest_sgent_cgenf_medium_tcp4,
     ttest_sgent_cgenf_medium_tcp6,

     ttest_sgent_cgenf_large_tcp4,
     ttest_sgent_cgenf_large_tcp6
    ].

%% Server: transport = gen_tcp, active = true
%% Client: transport = gen_tcp, active = once
ttest_sgent_cgeno_cases() ->
    [
     ttest_sgent_cgeno_small_tcp4,
     ttest_sgent_cgeno_small_tcp6,

     ttest_sgent_cgeno_medium_tcp4,
     ttest_sgent_cgeno_medium_tcp6,

     ttest_sgent_cgeno_large_tcp4,
     ttest_sgent_cgeno_large_tcp6
    ].

%% Server: transport = gen_tcp, active = true
%% Client: transport = gen_tcp, active = true
ttest_sgent_cgent_cases() ->
    [
     ttest_sgent_cgent_small_tcp4,
     ttest_sgent_cgent_small_tcp6,

     ttest_sgent_cgent_medium_tcp4,
     ttest_sgent_cgent_medium_tcp6,

     ttest_sgent_cgent_large_tcp4,
     ttest_sgent_cgent_large_tcp6
    ].

%% Server: transport = gen_tcp, active = true
%% Client: transport = socket(tcp)
ttest_sgent_csock_cases() ->
    [
     {group, ttest_sgent_csockf},
     {group, ttest_sgent_csocko},
     {group, ttest_sgent_csockt}
    ].

ttest_sgent_csockf_cases() ->
    [
     ttest_sgent_csockf_small_tcp4,
     ttest_sgent_csockf_small_tcp6,

     ttest_sgent_csockf_medium_tcp4,
     ttest_sgent_csockf_medium_tcp6,

     ttest_sgent_csockf_large_tcp4,
     ttest_sgent_csockf_large_tcp6
    ].

ttest_sgent_csocko_cases() ->
    [
     ttest_sgent_csocko_small_tcp4,
     ttest_sgent_csocko_small_tcp6,

     ttest_sgent_csocko_medium_tcp4,
     ttest_sgent_csocko_medium_tcp6,

     ttest_sgent_csocko_large_tcp4,
     ttest_sgent_csocko_large_tcp6
    ].

ttest_sgent_csockt_cases() ->
    [
     ttest_sgent_csockt_small_tcp4,
     ttest_sgent_csockt_small_tcp6,

     ttest_sgent_csockt_medium_tcp4,
     ttest_sgent_csockt_medium_tcp6,

     ttest_sgent_csockt_large_tcp4,
     ttest_sgent_csockt_large_tcp6
    ].

%% Server: transport = socket(tcp), active = false
ttest_ssockf_cases() ->
    [
     {group, ttest_ssockf_cgen},
     {group, ttest_ssockf_csock}
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = gen_tcp
ttest_ssockf_cgen_cases() ->
    [
     {group, ttest_ssockf_cgenf},
     {group, ttest_ssockf_cgeno},
     {group, ttest_ssockf_cgent}
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = gen_tcp, active = false
ttest_ssockf_cgenf_cases() ->
    [
     ttest_ssockf_cgenf_small_tcp4,
     ttest_ssockf_cgenf_small_tcp6,

     ttest_ssockf_cgenf_medium_tcp4,
     ttest_ssockf_cgenf_medium_tcp6,

     ttest_ssockf_cgenf_large_tcp4,
     ttest_ssockf_cgenf_large_tcp6
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = gen_tcp, active = once
ttest_ssockf_cgeno_cases() ->
    [
     ttest_ssockf_cgeno_small_tcp4,
     ttest_ssockf_cgeno_small_tcp6,

     ttest_ssockf_cgeno_medium_tcp4,
     ttest_ssockf_cgeno_medium_tcp6,

     ttest_ssockf_cgeno_large_tcp4,
     ttest_ssockf_cgeno_large_tcp6
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = gen_tcp, active = true
ttest_ssockf_cgent_cases() ->
    [
     ttest_ssockf_cgent_small_tcp4,
     ttest_ssockf_cgent_small_tcp6,

     ttest_ssockf_cgent_medium_tcp4,
     ttest_ssockf_cgent_medium_tcp6,

     ttest_ssockf_cgent_large_tcp4,
     ttest_ssockf_cgent_large_tcp6
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp)
ttest_ssockf_csock_cases() ->
    [
     {group, ttest_ssockf_csockf},
     {group, ttest_ssockf_csocko},
     {group, ttest_ssockf_csockt}
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp), active = false
ttest_ssockf_csockf_cases() ->
    [
     ttest_ssockf_csockf_small_tcp4,
     ttest_ssockf_csockf_small_tcp6,
     ttest_ssockf_csockf_small_tcpL,

     ttest_ssockf_csockf_medium_tcp4,
     ttest_ssockf_csockf_medium_tcp6,
     ttest_ssockf_csockf_medium_tcpL,

     ttest_ssockf_csockf_large_tcp4,
     ttest_ssockf_csockf_large_tcp6,
     ttest_ssockf_csockf_large_tcpL
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp), active = once
ttest_ssockf_csocko_cases() ->
    [
     ttest_ssockf_csocko_small_tcp4,
     ttest_ssockf_csocko_small_tcp6,
     ttest_ssockf_csocko_small_tcpL,

     ttest_ssockf_csocko_medium_tcp4,
     ttest_ssockf_csocko_medium_tcp6,
     ttest_ssockf_csocko_medium_tcpL,

     ttest_ssockf_csocko_large_tcp4,
     ttest_ssockf_csocko_large_tcp6,
     ttest_ssockf_csocko_large_tcpL
    ].

%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp), active = true
ttest_ssockf_csockt_cases() ->
    [
     ttest_ssockf_csockt_small_tcp4,
     ttest_ssockf_csockt_small_tcp6,
     ttest_ssockf_csockt_small_tcpL,

     ttest_ssockf_csockt_medium_tcp4,
     ttest_ssockf_csockt_medium_tcp6,
     ttest_ssockf_csockt_medium_tcpL,

     ttest_ssockf_csockt_large_tcp4,
     ttest_ssockf_csockt_large_tcp6,
     ttest_ssockf_csockt_large_tcpL
    ].

%% Server: transport = socket(tcp), active = once
ttest_ssocko_cases() ->
    [
     {group, ttest_ssocko_cgen},
     {group, ttest_ssocko_csock}
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = gen_tcp
ttest_ssocko_cgen_cases() ->
    [
     {group, ttest_ssocko_cgenf},
     {group, ttest_ssocko_cgeno},
     {group, ttest_ssocko_cgent}
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = gen_tcp, active = false
ttest_ssocko_cgenf_cases() ->
    [
     ttest_ssocko_cgenf_small_tcp4,
     ttest_ssocko_cgenf_small_tcp6,

     ttest_ssocko_cgenf_medium_tcp4,
     ttest_ssocko_cgenf_medium_tcp6,

     ttest_ssocko_cgenf_large_tcp4,
     ttest_ssocko_cgenf_large_tcp6
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = gen_tcp, active = once
ttest_ssocko_cgeno_cases() ->
    [
     ttest_ssocko_cgeno_small_tcp4,
     ttest_ssocko_cgeno_small_tcp6,

     ttest_ssocko_cgeno_medium_tcp4,
     ttest_ssocko_cgeno_medium_tcp6,

     ttest_ssocko_cgeno_large_tcp4,
     ttest_ssocko_cgeno_large_tcp6
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = gen_tcp, active = true
ttest_ssocko_cgent_cases() ->
    [
     ttest_ssocko_cgent_small_tcp4,
     ttest_ssocko_cgent_small_tcp6,

     ttest_ssocko_cgent_medium_tcp4,
     ttest_ssocko_cgent_medium_tcp6,

     ttest_ssocko_cgent_large_tcp4,
     ttest_ssocko_cgent_large_tcp6
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp)
ttest_ssocko_csock_cases() ->
    [
     {group, ttest_ssocko_csockf},
     {group, ttest_ssocko_csocko},
     {group, ttest_ssocko_csockt}
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp), active = false
ttest_ssocko_csockf_cases() ->
    [
     ttest_ssocko_csockf_small_tcp4,
     ttest_ssocko_csockf_small_tcp6,
     ttest_ssocko_csockf_small_tcpL,

     ttest_ssocko_csockf_medium_tcp4,
     ttest_ssocko_csockf_medium_tcp6,
     ttest_ssocko_csockf_medium_tcpL,

     ttest_ssocko_csockf_large_tcp4,
     ttest_ssocko_csockf_large_tcp6,
     ttest_ssocko_csockf_large_tcpL
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp), active = once
ttest_ssocko_csocko_cases() ->
    [
     ttest_ssocko_csocko_small_tcp4,
     ttest_ssocko_csocko_small_tcp6,
     ttest_ssocko_csocko_small_tcpL,

     ttest_ssocko_csocko_medium_tcp4,
     ttest_ssocko_csocko_medium_tcp6,
     ttest_ssocko_csocko_medium_tcpL,

     ttest_ssocko_csocko_large_tcp4,
     ttest_ssocko_csocko_large_tcp6,
     ttest_ssocko_csocko_large_tcpL
    ].

%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp), active = true
ttest_ssocko_csockt_cases() ->
    [
     ttest_ssocko_csockt_small_tcp4,
     ttest_ssocko_csockt_small_tcp6,
     ttest_ssocko_csockt_small_tcpL,

     ttest_ssocko_csockt_medium_tcp4,
     ttest_ssocko_csockt_medium_tcp6,
     ttest_ssocko_csockt_medium_tcpL,

     ttest_ssocko_csockt_large_tcp4,
     ttest_ssocko_csockt_large_tcp6,
     ttest_ssocko_csockt_large_tcpL
    ].

%% Server: transport = socket(tcp), active = true
ttest_ssockt_cases() ->
    [
     {group, ttest_ssockt_cgen},
     {group, ttest_ssockt_csock}
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = gen_tcp
ttest_ssockt_cgen_cases() ->
    [
     {group, ttest_ssockt_cgenf},
     {group, ttest_ssockt_cgeno},
     {group, ttest_ssockt_cgent}
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = gen_tcp, active = false
ttest_ssockt_cgenf_cases() ->
    [
     ttest_ssockt_cgenf_small_tcp4,
     ttest_ssockt_cgenf_small_tcp6,

     ttest_ssockt_cgenf_medium_tcp4,
     ttest_ssockt_cgenf_medium_tcp6,

     ttest_ssockt_cgenf_large_tcp4,
     ttest_ssockt_cgenf_large_tcp6
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = gen_tcp, active = once
ttest_ssockt_cgeno_cases() ->
    [
     ttest_ssockt_cgeno_small_tcp4,
     ttest_ssockt_cgeno_small_tcp6,

     ttest_ssockt_cgeno_medium_tcp4,
     ttest_ssockt_cgeno_medium_tcp6,

     ttest_ssockt_cgeno_large_tcp4,
     ttest_ssockt_cgeno_large_tcp6
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = gen_tcp, active = true
ttest_ssockt_cgent_cases() ->
    [
     ttest_ssockt_cgent_small_tcp4,
     ttest_ssockt_cgent_small_tcp6,

     ttest_ssockt_cgent_medium_tcp4,
     ttest_ssockt_cgent_medium_tcp6,

     ttest_ssockt_cgent_large_tcp4,
     ttest_ssockt_cgent_large_tcp6
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp)
ttest_ssockt_csock_cases() ->
    [
     {group, ttest_ssockt_csockf},
     {group, ttest_ssockt_csocko},
     {group, ttest_ssockt_csockt}
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp), active = false
ttest_ssockt_csockf_cases() ->
    [
     ttest_ssockt_csockf_small_tcp4,
     ttest_ssockt_csockf_small_tcp6,
     ttest_ssockt_csockf_small_tcpL,

     ttest_ssockt_csockf_medium_tcp4,
     ttest_ssockt_csockf_medium_tcp6,
     ttest_ssockt_csockf_medium_tcpL,

     ttest_ssockt_csockf_large_tcp4,
     ttest_ssockt_csockf_large_tcp6,
     ttest_ssockt_csockf_large_tcpL
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp), active = once
ttest_ssockt_csocko_cases() ->
    [
     ttest_ssockt_csocko_small_tcp4,
     ttest_ssockt_csocko_small_tcp6,
     ttest_ssockt_csocko_small_tcpL,

     ttest_ssockt_csocko_medium_tcp4,
     ttest_ssockt_csocko_medium_tcp6,
     ttest_ssockt_csocko_medium_tcpL,

     ttest_ssockt_csocko_large_tcp4,
     ttest_ssockt_csocko_large_tcp6,
     ttest_ssockt_csocko_large_tcpL
    ].

%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp), active = true
ttest_ssockt_csockt_cases() ->
    [
     ttest_ssockt_csockt_small_tcp4,
     ttest_ssockt_csockt_small_tcp6,
     ttest_ssockt_csockt_small_tcpL,

     ttest_ssockt_csockt_medium_tcp4,
     ttest_ssockt_csockt_medium_tcp6,
     ttest_ssockt_csockt_medium_tcpL,

     ttest_ssockt_csockt_large_tcp4,
     ttest_ssockt_csockt_large_tcp6,
     ttest_ssockt_csockt_large_tcpL
    ].

%% ticket_cases() ->
%%     [].



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

init_per_suite(Config) ->
    case lists:member(socket, erlang:loaded()) of
        true ->
            case os:type() of
                {win32, _} ->
                    (catch not_yet_implemented());
                _ ->
                    case quiet_mode(Config) of
                        default ->
                            ?LOGGER:start(),
                            Config;
                        Quiet ->
                            ?LOGGER:start(Quiet),
                            [{esock_test_quiet, Quiet}|Config]
                    end
            end;
        false ->
            {skip, "esock disabled"}
    end.

end_per_suite(_) ->
    (catch ?LOGGER:stop()),
    ok.


init_per_group(ttest = _GroupName, Config) ->
    io:format("init_per_group(~w) -> entry with"
              "~n   Config: ~p"
              "~n", [_GroupName, Config]),
    ttest_manager_start(),
    case lists:keysearch(esock_test_ttest_runtime, 1, Config) of
        {value, _} ->
            Config;
        false ->
            [{esock_test_ttest_runtime, which_ttest_runtime_env()} | Config]
    end;
init_per_group(_GroupName, Config) ->
    Config.

end_per_group(ttest = _GroupName, Config) ->
    io:format("init_per_group(~w) -> entry with"
              "~n   Config: ~p"
              "~n", [_GroupName, Config]),
    ttest_manager_stop(),
    lists:keydelete(esock_test_ttest_runtime, 1, Config);
end_per_group(_GroupName, Config) ->
    Config.


init_per_testcase(_TC, Config) ->
    io:format("init_per_testcase(~w) -> entry with"
              "~n   Config: ~p"
              "~n", [_TC, Config]),
    %% case quiet_mode(Config) of
    %%     default ->
    %%         ?LOGGER:start();
    %%     Quiet ->
    %%         ?LOGGER:start(Quiet)
    %% end,
    Config.

end_per_testcase(_TC, Config) ->
    %% ?LOGGER:stop(),
    Config.


quiet_mode(Config) ->
    case lists:keysearch(esock_test_quiet, 1, Config) of
        {value, {esock_test_quiet, Quiet}} ->
            Quiet;
        false ->
            case os:getenv("ESOCK_TEST_QUIET") of
                "true"  -> true;
                "false" -> false;
                _       -> default
            end
    end.


                
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                     %%
%%                           API MISC                                  %%
%%                                                                     %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% A simple test case that tests that the global debug can be channged.
%% At the same time, it will test the info function (since it uses it
%% for verification).

api_m_debug(suite) ->
    [];
api_m_debug(doc) ->
    [];
api_m_debug(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_m_debug,
           fun() -> has_bugfree_gcc() end,
           fun() ->
                   ok = api_m_debug()
           end).

%% For some reason this test case triggers a gcc bug, which causes
%% a segfault, on an ancient Fedora 16 VM. So, check the version of gcc...
%% Not pretty, but the simplest way to skip (without actually testing for the host).
has_bugfree_gcc() ->
    has_bugfree_gcc(os:type()).

%% Make sure we are on linux
has_bugfree_gcc({unix, linux}) ->
    has_bugfree_gcc2(os:cmd("cat /etc/issue"));
has_bugfree_gcc(_) ->
    ok.

%% Make sure we are on Fedora 16
has_bugfree_gcc2("Fedora release 16 " ++ _) ->
    has_bugfree_gcc3(os:cmd("gcc --version"));
has_bugfree_gcc2(_) ->
    ok.

has_bugfree_gcc3("gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2" ++ _) ->
    skip("Buggy GCC");
has_bugfree_gcc3(_) ->
    ok.

api_m_debug() ->
    i("get initial info"),
    #{debug := D0} = socket:info(),
    D1 = not D0,
    i("set new debug (~w => ~w)", [D0, D1]),
    ok = socket:debug(D1),
    i("get updated info (~w)", [D1]),
    #{debug := D1} = socket:info(),
    D2 = not D1,
    i("set new debug (~w => ~w)", [D1, D2]),
    ok = socket:debug(D2),
    i("get updated info (~w)", [D2]),
    #{debug := D2} = socket:info(),
    i("ok"),
    ok.
    

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                     %%
%%                           API BASIC                                 %%
%%                                                                     %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically open (create) and close an IPv4 UDP (dgram) socket.
%% With some extra checks...
api_b_open_and_close_udp4(suite) ->
    [];
api_b_open_and_close_udp4(doc) ->
    [];
api_b_open_and_close_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_open_and_close_udp4,
           fun() ->
                   InitState = #{domain   => inet,
                                 type     => dgram,
                                 protocol => udp},
                   ok = api_b_open_and_close(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically open (create) and close an IPv4 TCP (stream) socket.
%% With some extra checks...
api_b_open_and_close_tcp4(suite) ->
    [];
api_b_open_and_close_tcp4(doc) ->
    [];
api_b_open_and_close_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_open_and_close_tcp4,
           fun() ->
                   InitState = #{domain   => inet,
                                 type     => stream,
                                 protocol => tcp},
                   ok = api_b_open_and_close(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically open (create) and close an Unix Domain dgram (UDP) socket.
%% With some extra checks...
api_b_open_and_close_udpL(suite) ->
    [];
api_b_open_and_close_udpL(doc) ->
    [];
api_b_open_and_close_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_open_and_close_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain   => local,
                                 type     => dgram,
                                 protocol => default},
                   ok = api_b_open_and_close(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically open (create) and close an Unix Domain stream (TCP) socket.
%% With some extra checks...
api_b_open_and_close_tcpL(suite) ->
    [];
api_b_open_and_close_tcpL(doc) ->
    [];
api_b_open_and_close_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_open_and_close_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain   => local,
                                 type     => stream,
                                 protocol => default},
                   ok = api_b_open_and_close(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_b_open_and_close(InitState) ->
    Seq = 
        [
         #{desc => "open",
           cmd  => fun(#{domain   := Domain,
                         type     := Type,
                         protocol := Protocol} = S) -> 
                           Res = socket:open(Domain, Type, Protocol), 
                           {ok, {S, Res}} 
                   end},
         #{desc => "validate open",
           cmd  => fun({S, {ok, Sock}}) -> 
                           NewS = S#{socket => Sock},
                           {ok, NewS};
                      ({_, {error, _} = ERROR}) ->
                           ERROR
                   end},
         #{desc => "get domain (maybe)",
           cmd  => fun(#{socket := Sock} = S) ->
                           Res = socket:getopt(Sock, socket, domain),
                           {ok, {S, Res}}
                   end},
         #{desc => "validate domain (maybe)",
           cmd  => fun({#{domain := Domain} = S, {ok, Domain}}) -> 
                           {ok, S};
                      ({#{domain := ExpDomain}, {ok, Domain}}) ->
                           {error, {unexpected_domain, ExpDomain, Domain}};
                      %% Some platforms do not support this option
                      ({S, {error, einval}}) ->
                           {ok, S};
                      ({_, {error, _} = ERROR}) ->
                           ERROR
                   end},
         #{desc => "get type",
           cmd  => fun(#{socket := Sock} = State) ->
                           Res = socket:getopt(Sock, socket, type), 
                           {ok, {State, Res}}
                   end},
         #{desc => "validate type",
           cmd  => fun({#{type := Type} = State, {ok, Type}}) ->
                           {ok, State};
                      ({#{type := ExpType}, {ok, Type}}) ->
                           {error, {unexpected_type, ExpType, Type}};
                      ({_, {error, _} = ERROR}) ->
                           ERROR
                   end},
         #{desc => "get protocol",
           cmd  => fun(#{socket := Sock} = State) ->
			   case socket:supports(options, socket, protocol) of
			       true ->
				   Res = socket:getopt(Sock, socket, protocol),
				   {ok, {State, Res}};
			       false ->
				   {ok, {State, not_supported}}
			   end
                   end},
         #{desc => "validate protocol",
           cmd  => fun({State, not_supported}) ->
			   ?SEV_IPRINT("socket option 'protocol' "
				       "not supported"),
                           {ok, State};
                      ({#{protocol := Protocol} = State, {ok, Protocol}}) ->
                           {ok, State};
                      ({#{protocol := ExpProtocol}, {ok, Protocol}}) ->
                           {error, {unexpected_type, ExpProtocol, Protocol}};
                      ({_, {error, _} = ERROR}) ->
                           ERROR
                   end},
         #{desc => "get controlling-process",
           cmd  => fun(#{socket := Sock} = State) ->
                           Res = socket:getopt(Sock, otp, controlling_process),
                           {ok, {State, Res}}
                   end},
         #{desc => "validate controlling-process",
           cmd  => fun({State, {ok, Pid}}) ->
                           case self() of
                               Pid ->
                                   {ok, State};
                               _ ->
                                   {error, {unexpected_owner, Pid}}
                           end;
                      ({_, {error, _} = ERROR}) ->
                           ERROR
                   end},
         #{desc => "close socket",
           cmd  => fun(#{socket := Sock} = State) ->
                           Res = socket:close(Sock),
                           {ok, {State, Res}}
                   end},
         #{desc => "validate socket close",
           cmd  => fun({_, ok}) ->
                           ok;
                      ({_, {error, _} = ERROR}) ->
                           ERROR
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],
    Evaluator = ?SEV_START("tester", Seq, InitState),
    ok = ?SEV_AWAIT_FINISH([Evaluator]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive on an IPv4 UDP (dgram) socket using
%% sendto and recvfrom..
api_b_sendto_and_recvfrom_udp4(suite) ->
    [];
api_b_sendto_and_recvfrom_udp4(doc) ->
    [];
api_b_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_sendto_and_recvfrom_udp4,
           fun() ->
                   Send = fun(Sock, Data, Dest) ->
                                  socket:sendto(Sock, Data, Dest)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recvfrom(Sock)
                          end,
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive on an IPv4 UDP (dgram) socket using
%% sendto and recvfrom.
api_b_sendto_and_recvfrom_udpL(suite) ->
    [];
api_b_sendto_and_recvfrom_udpL(doc) ->
    [];
api_b_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_sendto_and_recvfrom_udpL,
           fun() ->
                   has_support_unix_domain_socket(),
                   unix_domain_socket_host_cond()
           end,
           fun() ->
                   Send = fun(Sock, Data, Dest) ->
                                  socket:sendto(Sock, Data, Dest)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recvfrom(Sock)
                          end,
                   InitState = #{domain => local,
                                 proto  => default,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive on an IPv4 UDP (dgram) socket
%% using sendmsg and recvmsg.
api_b_sendmsg_and_recvmsg_udp4(suite) ->
    [];
api_b_sendmsg_and_recvmsg_udp4(doc) ->
    [];
api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_sendmsg_and_recvmsg_udp4,
           fun() ->
                   Send = fun(Sock, Data, Dest) ->
                                  %% We need tests for this,
                                  %% but this is not the place it.
                                  %% CMsgHdr  = #{level => ip,
                                  %%              type  => tos,
                                  %%              data  => reliability},
                                  %% CMsgHdrs = [CMsgHdr],
                                  MsgHdr = #{addr => Dest,
                                             %% ctrl => CMsgHdrs,
                                             iov  => [Data]},
                                  socket:sendmsg(Sock, MsgHdr)
                          end,
                   Recv = fun(Sock) ->
                                  %% We have some issues on old darwing...
                                  %% socket:setopt(Sock, otp, debug, true),
                                  case socket:recvmsg(Sock) of
                                      {ok, #{addr  := Source,
                                             iov   := [Data]}} ->
                                          %% socket:setopt(Sock, otp, debug, false),
                                          {ok, {Source, Data}};
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive on an IPv4 UDP (dgram) socket
%% using sendmsg and recvmsg.
api_b_sendmsg_and_recvmsg_udpL(suite) ->
    [];
api_b_sendmsg_and_recvmsg_udpL(doc) ->
    [];
api_b_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_b_sendmsg_and_recvmsg_udpL,
           fun() ->
                   has_support_unix_domain_socket(),
                   unix_domain_socket_host_cond()
           end,
           fun() ->
                   Send = fun(Sock, Data, Dest) ->
                                  %% We need tests for this,
                                  %% but this is not the place it.
                                  %% CMsgHdr  = #{level => ip,
                                  %%              type  => tos,
                                  %%              data  => reliability},
                                  %% CMsgHdrs = [CMsgHdr],
                                  MsgHdr = #{addr => Dest,
                                             %% ctrl => CMsgHdrs,
                                             iov  => [Data]},
                                  socket:sendmsg(Sock, MsgHdr)
                          end,
                   Recv = fun(Sock) ->
                                  %% We have some issues on old darwing...
                                  %% socket:setopt(Sock, otp, debug, true),
                                  case socket:recvmsg(Sock) of
                                      {ok, #{addr  := Source,
                                             iov   := [Data]}} ->
                                          %% socket:setopt(Sock, otp, debug, false),
                                          {ok, {Source, Data}};
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => local,
                                 proto  => default,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_b_send_and_recv_udp(InitState) ->
    Seq = 
        [
         #{desc => "local address",
           cmd  => fun(#{domain := local = Domain} = State) ->
                           LSASrc = which_local_socket_addr(Domain),
                           LSADst = which_local_socket_addr(Domain),
                           {ok, State#{lsa_src => LSASrc,
                                       lsa_dst => LSADst}};
                      (#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa_src => LSA,
                                       lsa_dst => LSA}}
                   end},

         #{desc => "open src socket",
           cmd  => fun(#{domain := Domain,
                         proto  := Proto} = State) ->
                           Sock = sock_open(Domain, dgram, Proto),
                           {ok, State#{sock_src => Sock}}
                   end},
         #{desc => "bind src",
           cmd  => fun(#{sock_src := Sock, lsa_src := LSA}) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ?SEV_IPRINT("src bound"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("src bind failed: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "sockname src socket",
           cmd  => fun(#{sock_src := Sock} = State) ->
                           SASrc = sock_sockname(Sock),
                           ?SEV_IPRINT("src sockaddr: "
                                       "~n   ~p", [SASrc]),
                           {ok, State#{sa_src => SASrc}}
                   end},

         #{desc => "open dst socket",
           cmd  => fun(#{domain := Domain,
                         proto  := Proto} = State) ->
                           Sock = sock_open(Domain, dgram, Proto),
                           {ok, State#{sock_dst => Sock}}
                   end},
         #{desc => "bind dst",
           cmd  => fun(#{sock_dst := Sock, lsa_dst := LSA}) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ?SEV_IPRINT("src bound"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("src bind failed: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "sockname dst socket",
           cmd  => fun(#{sock_dst := Sock} = State) ->
                           SADst = sock_sockname(Sock),
                           ?SEV_IPRINT("dst sockaddr: "
                                       "~n   ~p", [SADst]),
                           {ok, State#{sa_dst => SADst}}
                   end},
         #{desc => "send req (to dst)",
           cmd  => fun(#{sock_src := Sock, sa_dst := Dst, send := Send}) ->
                           Send(Sock, ?BASIC_REQ, Dst)
                   end},
         #{desc => "recv req (from src)",
           cmd  => fun(#{sock_dst := Sock, sa_src := Src, recv := Recv}) ->
                           case Recv(Sock) of
                               {ok, {Src, ?BASIC_REQ}} ->
                                   ok;
                               {ok, UnexpData} ->
                                   {error, {unexpected_data, UnexpData}};
                               {error, _} = ERROR ->
                                   %% At the moment there is no way to get
                                   %% status or state for the socket...
                                   ERROR
                           end
                   end},
         #{desc => "send rep (to src)",
           cmd  => fun(#{sock_dst := Sock, sa_src := Src, send := Send}) ->
                           Send(Sock, ?BASIC_REP, Src)
                   end},
         #{desc => "recv rep (from dst)",
           cmd  => fun(#{sock_src := Sock, sa_dst := Dst, recv := Recv}) ->
                           case Recv(Sock) of
                               {ok, {Dst, ?BASIC_REP}} ->
                                   ok;
                               {ok, UnexpData} ->
                                   {error, {unexpected_data, UnexpData}};
                               {error, _} = ERROR ->
                                   %% At the moment there is no way to get
                                   %% status or state for the socket...
                                   ERROR
                           end
                   end},
         #{desc => "close src socket",
           cmd  => fun(#{domain   := local,
                         sock_src := Sock,
                         lsa_src  := #{path := Path}} = State) ->
                           ok = socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() -> maps:remove(lsa_src, State) end,
                                           fun() -> State end),
                           {ok, maps:remove(sock_src, State1)};
                      (#{sock_src := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(sock_src, State)}
                   end},
         #{desc => "close dst socket",
           cmd  => fun(#{domain   := local,
                         sock_dst := Sock,
                         lsa_dst  := #{path := Path}} = State) ->
                           ok = socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() -> maps:remove(lsa_dst, State) end,
                                           fun() -> State end),
                           {ok, maps:remove(sock_dst, State1)};
                      (#{sock_dst := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(sock_dst, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],
    Evaluator = ?SEV_START("tester", Seq, InitState),
    ok = ?SEV_AWAIT_FINISH([Evaluator]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive using the "common" functions (send and recv)
%% on an IPv4 TCP (stream) socket.
api_b_send_and_recv_tcp4(suite) ->
    [];
api_b_send_and_recv_tcp4(doc) ->
    [];
api_b_send_and_recv_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_b_send_and_recv_tcp4,
           fun() ->
                   Send = fun(Sock, Data) ->
                                  socket:send(Sock, Data)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recv(Sock)
                          end,
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive using the "common" functions (send and recv)
%% on an Unix Domain (stream) socket (TCP).
api_b_send_and_recv_tcpL(suite) ->
    [];
api_b_send_and_recv_tcpL(doc) ->
    [];
api_b_send_and_recv_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_b_send_and_recv_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Send = fun(Sock, Data) ->
                                  socket:send(Sock, Data)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recv(Sock)
                          end,
                   InitState = #{domain => local,
                                 proto  => default,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an IPv4 TCP (stream) socket.
api_b_sendmsg_and_recvmsg_tcp4(suite) ->
    [];
api_b_sendmsg_and_recvmsg_tcp4(doc) ->
    [];
api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_b_sendmsg_and_recvmsg_tcp4,
           fun() ->
                   Send = fun(Sock, Data) ->
                                  MsgHdr = #{iov => [Data]},
                                  socket:sendmsg(Sock, MsgHdr)
                          end,
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock) of
                                      {ok, #{addr  := undefined,
                                             iov   := [Data]}} ->
                                          {ok, Data};
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an Unix Domain (stream) socket (TCP).
api_b_sendmsg_and_recvmsg_tcpL(suite) ->
    [];
api_b_sendmsg_and_recvmsg_tcpL(doc) ->
    [];
api_b_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_b_sendmsg_and_recvmsg_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Send = fun(Sock, Data) ->
                                  MsgHdr = #{iov => [Data]},
                                  socket:sendmsg(Sock, MsgHdr)
                          end,
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock) of
                                      %% On some platforms, the address
                                      %% is *not* provided (e.g. FreeBSD)
                                      {ok, #{addr  := undefined,
                                             iov   := [Data]}} ->
                                          {ok, Data};
                                      %% On some platforms, the address
                                      %% *is* provided (e.g. linux)
                                      {ok, #{addr  := #{family := local},
                                             iov   := [Data]}} ->
                                          socket:setopt(Sock, 
                                                        otp, 
                                                        debug, 
                                                        false),
                                          {ok, Data};
                                      {error, _} = ERROR ->
                                          socket:setopt(Sock, 
                                                        otp, 
                                                        debug, 
                                                        false),
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => local,
                                 proto  => default,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_b_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_b_send_and_recv_tcp(InitState) ->
    process_flag(trap_exit, true),
    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain,
                         proto  := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{domain := local,
                         lsock  := LSock,
                         lsa    := LSA} = _State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, _Port} ->
                                   ok; % We do not care about the port for local
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{lsock := LSock, lsa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("bound to port: ~w", [Port]),
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain := local,
                         tester := Tester, lsa := #{path := Path}}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Path),
                           ok;
                      (#{tester := Tester, lport := Port}) ->
                           %% This is actually not used for unix domain socket
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "await connection",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("accepted: ~n   ~p", [Sock]),
                                   {ok, State#{csock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},
         #{desc => "await (recv) request",
           cmd  => fun(#{csock := Sock, recv := Recv}) ->
                           case Recv(Sock) of
                               {ok, ?BASIC_REQ} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv request)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_req),
                           ok
                   end},
         #{desc => "await continue (with send reply)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_reply)
                   end},
         #{desc => "send reply",
           cmd  => fun(#{csock := Sock, send := Send}) ->
                           Send(Sock, ?BASIC_REP)
                   end},
         #{desc => "announce ready (send reply)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_reply),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close connection socket",
           cmd  => fun(#{csock := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(csock, State)}
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{domain   := local,
                         lsock    := Sock,
                         local_sa := #{path := Path}} = State) ->
                           ok = socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() ->
                                                   maps:remove(local_sa, State)
                                           end,
                                           fun() -> State end),
                           {ok, maps:remove(lsock, State1)};
                      (#{lsock := LSock} = State) ->
                           case socket:close(LSock) of
                               ok ->
                                   {ok, maps:remove(lsock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(#{domain := local} = State) ->
                           {Tester, Path} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, server_path => Path}};
                      (State) ->
                           {Tester, Port} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, server_port => Port}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** The init part ***
         #{desc => "which server (local) address",
           cmd  => fun(#{domain      := local = Domain,
                         server_path := Path} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           SSA = #{family => Domain, path => Path},
                           {ok, State#{local_sa => LSA, server_sa => SSA}};
                      (#{domain := Domain, server_port := Port} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           SSA = LSA#{port => Port},
                           {ok, State#{local_sa => LSA, server_sa => SSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain,
                         proto  := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect)
                   end},
         #{desc => "connect to server",
           cmd  => fun(#{sock := Sock, server_sa := SSA}) ->
                           socket:connect(Sock, SSA)
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},
         #{desc => "await continue (send request)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_req)
                   end},
         #{desc => "send request (to server)",
           cmd  => fun(#{sock := Sock, send := Send}) ->
                           Send(Sock, ?BASIC_REQ)
                   end},
         #{desc => "announce ready (send request)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_req),
                           ok
                   end},
         #{desc => "await recv reply (from server)",
           cmd  => fun(#{sock := Sock, recv := Recv}) ->
                           {ok, ?BASIC_REP} = Recv(Sock),
                           ok
                   end},
         #{desc => "announce ready (recv reply)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_reply),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{domain   := local,
                         sock     := Sock,
                         local_sa := #{path := Path}} = State) ->
                           ok = socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() ->
                                                   maps:remove(local_sa, State)
                                           end,
                                           fun() -> State end),
                           {ok, maps:remove(sock, State1)};
                      (#{sock := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_port => Port}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client := Pid, server_port := Port} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Port),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},

         %% *** The actual test ***
         #{desc => "order server to continue (with accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client to continue (with connect)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, connect),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, connect)
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept)
                   end},
         #{desc => "order client to continue (with send request)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send_req),
                           ok
                   end},
         #{desc => "await client ready (with send request)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, send_req)
                   end},
         #{desc => "await server ready (request recv)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, recv_req)
                   end},
         #{desc => "order server to continue (with send reply)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, send_reply),
                           ok
                   end},
         #{desc => "await server ready (with reply sent)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, send_reply)
                   end},
         #{desc => "await client ready (reply recv)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, recv_reply)
                   end},


         %% *** Termination ***
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client, State),
                           {ok, State1}
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server, State),
                           {ok, State1}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start client evaluator"),
    Client = ?SEV_START("client", ClientSeq, InitState),
    i("await evaluator(s)"),

    i("start tester evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically establish a TCP connection via an async connect. 

api_a_connect_tcp4(suite) ->
    [];
api_a_connect_tcp4(doc) ->
    [];
api_a_connect_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_connect_tcp4,
           fun() ->
                   Connect = fun(Sock, SockAddr) ->
                                     socket:connect(Sock, SockAddr, nowait)
                             end,
                   Send = fun(Sock, Data) ->
                                  socket:send(Sock, Data)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recv(Sock)
                          end,
                   InitState = #{domain  => inet,
                                 connect => Connect,
                                 send    => Send,
                                 recv    => Recv},
                   ok = api_a_connect_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_connect_tcp(InitState) ->
    process_flag(trap_exit, true),
    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "await connection",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("accepted: ~n   ~p", [Sock]),
                                   {ok, State#{csock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         #{desc => "await continue (recv_req)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_req)
                   end},
         #{desc => "recv req",
           cmd  => fun(#{csock := Sock, recv := Recv}) ->
                           case Recv(Sock) of
                               {ok, ?BASIC_REQ} ->
                                   ok;
                               {ok, UnexpData} ->
                                   {error, {unexpected_data, UnexpData}};
                               {error, _} = ERROR ->
                                   %% At the moment there is no way to get
                                   %% status or state for the socket...
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_req)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_req),
                           ok
                   end},
         #{desc => "await continue (send_rep)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_rep)
                   end},
         #{desc => "send rep",
           cmd  => fun(#{csock := Sock, send := Send}) ->
                           Send(Sock, ?BASIC_REP)
                   end},
         #{desc => "announce ready (send_rep)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_rep),
                           ok
                   end},
	 

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close connection socket",
           cmd  => fun(#{csock := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(csock, State)}
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{lsock := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(lsock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           {Tester, Port} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, server_port => Port}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** The init part ***
         #{desc => "which server (local) address",
           cmd  => fun(#{domain := Domain, server_port := Port} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           SSA = LSA#{port => Port},
                           {ok, State#{local_sa => LSA, server_sa => SSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (async connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, async_connect)
                   end},
         #{desc => "connect (async) to server",
           cmd  => fun(#{sock      := Sock,
                         server_sa := SSA,
                         connect   := Connect} = State) ->
                           case Connect(Sock, SSA) of
                               ok ->
                                   ?SEV_IPRINT("ok -> "
					       "unexpected success => SKIP", 
                                               []),
                                   {skip, unexpected_success};
                               {select, {select_info, ST, SR}} ->
                                   ?SEV_IPRINT("select ->"
                                               "~n   tag: ~p"
                                               "~n   ref: ~p", [ST, SR]),
                                   {ok, State#{connect_stag => ST,
                                               connect_sref => SR}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (connect select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{sock := Sock, connect_sref := Ref}) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   ?SEV_IPRINT("select message ->"
                                               "~n   ref: ~p", [Ref]),
                                   ok
                           after 5000 ->
                                   ?SEV_EPRINT("timeout: "
                                               "~n   message queue: ~p",
                                               [mq()]),
                                   {error, timeout}
                           end
                   end},
         #{desc => "announce ready (select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, select),
                           ok
                   end},
         #{desc => "connect (async) to server",
           cmd  => fun(#{sock := Sock, server_sa := SSA, connect := Connect}) ->
                           case Connect(Sock, SSA) of
                               ok ->
                                   ok;
                               {select, SelectInfo} ->
                                   {error, {unexpected_select, SelectInfo}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},
         #{desc => "get peername",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case socket:peername(Sock) of
                               {ok, SockAddr} ->
                                   ?SEV_IPRINT("Peer Name: ~p", [SockAddr]),
                                   ok;
                                {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "await continue (send_req)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_req)
                   end},
         #{desc => "send req",
           cmd  => fun(#{sock := Sock, send := Send}) ->
                           Send(Sock, ?BASIC_REQ)
                   end},
         #{desc => "announce ready (send_req)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_req),
                           ok
                   end},
         #{desc => "await continue (recv_rep)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_rep)
                   end},
         #{desc => "recv rep",
           cmd  => fun(#{sock := Sock, recv := Recv}) ->
                           case Recv(Sock) of
                               {ok, ?BASIC_REP} ->
                                   ok;
                               {ok, UnexpData} ->
                                   {error, {unexpected_data, UnexpData}};
                               {error, _} = ERROR ->
                                   %% At the moment there is no way to get
                                   %% status or state for the socket...
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_rep)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_rep),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           ok = socket:close(Sock),
                           State2 = maps:remove(sock,         State),
                           State3 = maps:remove(connect_stag, State2),
                           State4 = maps:remove(connect_sref, State3),
                           {ok, State4}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_port => Port}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client := Pid, server_port := Port} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Port),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},


         %% *** The actual test ***
         #{desc => "order client to continue (async connect)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, async_connect),
                           ok
                   end},
         #{desc => "await client ready (connect select)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, connect_select)
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "order server to continue (with accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept),
                           ok
                   end},
         #{desc => "await client ready (select)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, select)
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, connect)
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept)
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "order server to recv test req (recv req)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, recv_req),
                           ok
                   end},
         #{desc => "order client to send test req (send req)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send_req),
                           ok
                   end},
         #{desc => "await client ready (send_req)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, send_req)
                   end},
         #{desc => "await server ready (recv_req)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, recv_req)
                   end},
         #{desc => "order client to recv test rep (send rep)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, recv_rep),
                           ok
                   end},
         #{desc => "order server to send test rep (send rep)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, send_rep),
                           ok
                   end},
         #{desc => "await server ready (send_rep)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, send_rep)
                   end},
         #{desc => "await client ready (recv_rep)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, recv_rep)
                   end},


         %% *** Termination ***
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client, State),
                           {ok, State1}
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server, State),
                           {ok, State1}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start client evaluator"),
    Client = ?SEV_START("client", ClientSeq, InitState),
    i("await evaluator(s)"),

    i("start tester evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive on an IPv4 UDP (dgram) socket using
%% sendto and recvfrom. But we try to be async. That is, we use
%% the 'nowait' value for the Timeout argument (and await the eventual
%% select message). Note that we only do this for the recvfrom,
%% since its much more difficult to "arrange" for sendto.
%%
api_a_sendto_and_recvfrom_udp4(suite) ->
    [];
api_a_sendto_and_recvfrom_udp4(doc) ->
    [];
api_a_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_a_sendto_and_recvfrom_udp4,
           fun() ->
                   Send = fun(Sock, Data, Dest) ->
                                  socket:sendto(Sock, Data, Dest)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recvfrom(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_a_send_and_recv_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive on an IPv4 UDP (dgram) socket using
%% sendto and recvfrom. But we try to be async. That is, we use
%% the 'nowait' value for the Timeout argument (and await the eventual
%% select message). Note that we only do this for the recvmsg,
%% since its much more difficult to "arrange" for sendmsg.
%%
api_a_sendmsg_and_recvmsg_udp4(suite) ->
    [];
api_a_sendmsg_and_recvmsg_udp4(doc) ->
    [];
api_a_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_a_sendmsg_and_recvmsg_udp4,
           fun() ->
                   Send = fun(Sock, Data, Dest) ->
                                  MsgHdr = #{addr => Dest,
                                             %% ctrl => CMsgHdrs,
                                             iov  => [Data]},
                                  socket:sendmsg(Sock, MsgHdr)
                          end,
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock, nowait) of
                                      {ok, #{addr  := Source,
                                             iov   := [Data]}} ->
                                          {ok, {Source, Data}};
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_a_send_and_recv_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_send_and_recv_udp(InitState) ->
    ServerSeq = 
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind socket (to local address)",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{port => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, local_sa := LSA, port := Port}) ->
                           ServerSA = LSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, {select_info, Tag, RecvRef}} ->
                                   ?SEV_IPRINT("expected select: "
                                               "~n   Tag: ~p"
                                               "~n   Ref: ~p", [Tag, RecvRef]),
                                   {ok, State#{recv_stag => Tag,
                                               recv_sref => RecvRef}};
                               {ok, X} ->
                                   {error, {unexpected_succes, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{sock := Sock, recv_sref := RecvRef}) ->
                           receive
                               {'$socket', Sock, select, RecvRef} ->
                                   ok
                           after 5000 ->
                                   ?SEV_EPRINT("message queue: ~p", [mq()]),
                                   {error, timeout}
                           end
                   end},
         #{desc => "announce ready (select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, select),
                           ok
                   end},
         #{desc => "now read the data (request)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {ok, {Src, ?BASIC_REQ}} ->
                                   {ok, State#{req_src => Src}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv request)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_req),
                           ok
                   end},

         #{desc => "await continue (send reply)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_reply)
                   end},
         #{desc => "send reply",
           cmd  => fun(#{sock := Sock, req_src := Src, send := Send}) ->
                           Send(Sock, ?BASIC_REP, Src)
                   end},
         #{desc => "announce ready (send)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   State2 = maps:remove(tester,    State),
                                   State3 = maps:remove(recv_stag, State2),
                                   State4 = maps:remove(recv_sref, State3),
                                   State5 = maps:remove(req_src,   State4),
                                   {ok, State5};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    ClientSeq = 
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, ServerSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester, 
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "open socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           Sock = sock_open(Domain, dgram, udp),
                           SA   = sock_sockname(Sock),
                           {ok, State#{sock => Sock, sa => SA}}
                   end},
         #{desc => "bind socket (to local address)",
           cmd  => fun(#{sock := Sock, lsa := LSA}) ->
                          case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (send request)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_req)
                   end},
         #{desc => "send request",
           cmd  => fun(#{sock := Sock, server_sa := Server, send := Send}) ->
                           Send(Sock, ?BASIC_REQ, Server)
                   end},
         #{desc => "announce ready (send request)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_req),
                           ok
                   end},
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv reply (with nowait)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, {select_info, Tag, RecvRef}} ->
                                   {ok, State#{recv_stag => Tag,
                                               recv_sref => RecvRef}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{sock := Sock, recv_sref := RecvRef}) ->
                           receive
                               {'$socket', Sock, select, RecvRef} ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, select),
                           ok
                   end},
         #{desc => "now read the data (reply)",
           cmd  => fun(#{sock := Sock, recv := Recv}) ->
                           case Recv(Sock) of
                               {ok, {_Src, ?BASIC_REP}} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv reply)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_rep),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   State2 = maps:remove(tester,    State),
                                   State3 = maps:remove(recv_stag, State2),
                                   State4 = maps:remove(recv_sref, State3),
                                   {ok, State4};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    TesterSeq = 
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client    := Pid, 
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, ServerSA),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},
 
         %% The actual test
         #{desc => "order server continue (recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await server ready (recv_select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, recv_select)
                   end},

         #{desc => "order client continue (send request)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send_req),
                           ok
                   end},
         #{desc => "await client ready (send request)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, send_req)
                   end},
         #{desc => "await server ready (select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, select)
                   end},
         #{desc => "await server ready (recv request)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, recv_req)
                   end},

         #{desc => "order client continue (recv)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await client ready (recv_select)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, recv_select)
                   end},
         #{desc => "order server continue (send reply)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send_reply),
                           ok
                   end},
         #{desc => "await server ready (send)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, send)
                   end},
         #{desc => "await client ready (select)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, select)
                   end},
         #{desc => "await client ready (recv reply)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, recv_rep)
                   end},

         %% Terminations
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    ServerInitState = InitState,
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator(s)"),
    ClientInitState = InitState,
    Client = ?SEV_START("client", ClientSeq, ClientInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive using the "common" functions (send and recv)
%% on an IPv4 TCP (stream) socket. But we try to be async. That is, we use
%% the 'nowait' value for the Timeout argument (and await the eventual
%% select message). Note that we only do this for the recv,
%% since its much more difficult to "arrange" for send.
%% We *also* test async for accept.
api_a_send_and_recv_tcp4(suite) ->
    [];
api_a_send_and_recv_tcp4(doc) ->
    [];
api_a_send_and_recv_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_send_and_recv_tcp4,
           fun() ->
                   Send = fun(Sock, Data) ->
                                  socket:send(Sock, Data)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recv(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_a_send_and_recv_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an IPv4 TCP (stream) socket. But we try to be async. That is, we use
%% the 'nowait' value for the Timeout argument (and await the eventual
%% select message). Note that we only do this for the recvmsg,
%% since its much more difficult to "arrange" for sendmsg.
%% We *also* test async for accept.
api_a_sendmsg_and_recvmsg_tcp4(suite) ->
    [];
api_a_sendmsg_and_recvmsg_tcp4(doc) ->
    [];
api_a_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_sendmsg_and_recvmsg_tcp4,
           fun() ->
                   Send = fun(Sock, Data) ->
                                  MsgHdr = #{iov => [Data]},
                                  socket:sendmsg(Sock, MsgHdr)
                          end,
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock, nowait) of
                                      {ok, #{addr  := undefined,
                                             iov   := [Data]}} ->
                                          {ok, Data};
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                     {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 send   => Send,
                                 recv   => Recv},
                   ok = api_a_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_send_and_recv_tcp(InitState) ->
    process_flag(trap_exit, true),
    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "await connection (nowait)",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock, nowait) of
                               {select, {select_info, Tag, Ref}} ->
                                   ?SEV_IPRINT("accept select: "
                                               "~n   Tag: ~p"
                                               "~n   Ref: ~p", [Tag, Ref]),
                                   {ok, State#{accept_stag => Tag,
                                               accept_sref => Ref}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{lsock := Sock, accept_sref := Ref}) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, select),
                           ok
                   end},
         #{desc => "await connection (again)",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock, nowait) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("accepted: "
                                               "~n   Sock: ~p", [Sock]),
                                   {ok, State#{csock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         #{desc => "await continue (recv request)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_req)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{csock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, {select_info, Tag, Ref}} ->
                                   ?SEV_IPRINT("recv select: "
                                               "~n   Tag: ~p"
                                               "~n   Ref: ~p", [Tag, Ref]),
                                   {ok, State#{recv_stag => Tag,
                                               recv_sref => Ref}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{csock := Sock, recv_sref := RecvRef}) ->
                           receive
                               {'$socket', Sock, select, RecvRef} ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, select),
                           ok
                   end},
         #{desc => "now read the data (request)",
           cmd  => fun(#{csock := Sock, recv := Recv} = _State) ->
                           case Recv(Sock) of
                               {ok, ?BASIC_REQ} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv request)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_req),
                           ok
                   end},

         #{desc => "await continue (send reply)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_rep)
                   end},
         #{desc => "send reply",
           cmd  => fun(#{csock := Sock, send := Send}) ->
                           Send(Sock, ?BASIC_REP)
                   end},
         #{desc => "announce ready (send reply)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_rep),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close connection socket",
           cmd  => fun(#{csock := Sock}) ->
                           socket:close(Sock)
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{lsock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    ClientSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           {Tester, Port} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, server_port => Port}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** The init part ***
         #{desc => "which server (local) address",
           cmd  => fun(#{domain := Domain, server_port := Port} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           SSA = LSA#{port => Port},
                           {ok, State#{local_sa => LSA, server_sa => SSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect)
                   end},
         #{desc => "connect to server",
           cmd  => fun(#{sock := Sock, server_sa := SSA}) ->
                           socket:connect(Sock, SSA)
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         #{desc => "await continue (send request)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_req)
                   end},
         #{desc => "send request (to server)",
           cmd  => fun(#{sock := Sock, send := Send}) ->
                           ok = Send(Sock, ?BASIC_REQ)
                   end},
         #{desc => "announce ready (send request)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_req),
                           ok
                   end},

         #{desc => "try recv reply (with nowait, expect select)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, {select_info, Tag, Ref}} ->
                                   ?SEV_IPRINT("recv select: "
                                               "~n   Tag: ~p"
                                               "~n   Ref: ~p", [Tag, Ref]),
                                   {ok, State#{recv_stag => Tag,
                                               recv_sref => Ref}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{sock := Sock, recv_sref := RecvRef}) ->
                           receive
                               {'$socket', Sock, select, RecvRef} ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, select),
                           ok
                   end},
         #{desc => "now read the data (reply)",
           cmd  => fun(#{sock := Sock, recv := Recv}) ->
                           {ok, ?BASIC_REP} = Recv(Sock),
                           ok
                   end},
         #{desc => "announce ready (recv reply)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_rep),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_port => Port}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client := Pid, server_port := Port} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Port),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},

         %% *** The actual test ***
         #{desc => "order server to continue (with accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept),
                           ok
                   end},
         #{desc => "await server ready (accept select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, accept_select)
                   end},
         #{desc => "order client to continue (with connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await server ready (select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, select)
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, accept)
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, client, connect)
                   end},

         #{desc => "order server to continue (recv request)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv_req),
                           ok
                   end},
         #{desc => "await server ready (recv select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, recv_select)
                   end},
         #{desc => "order client to continue (send request)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send_req),
                           ok
                   end},
         #{desc => "await client ready (send request)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, send_req)
                   end},
         #{desc => "await server ready (select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, select)
                   end},
         #{desc => "await server ready (recv request)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, recv_req)
                   end},

         #{desc => "order client to continue (recv reply)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv_rep),
                           ok
                   end},
         #{desc => "await client ready (recv select)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, client, recv_select)
                   end},
         #{desc => "order server to continue (send reply)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send_rep),
                           ok
                   end},
         #{desc => "await server ready (send reply)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, send_rep)
                   end},
         #{desc => "await client ready (select)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, client, select)
                   end},
         #{desc => "await client ready (reply recv)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, recv_rep)
                   end},


         %% *** Termination ***
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client, State),
                           {ok, State1}
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server, State),
                           {ok, State1}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start client evaluator"),
    Client = ?SEV_START("client", ClientSeq, InitState),

    i("start tester evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).





%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make an async (Timeout = nowait) call to recvfrom,
%% wait some time and then cancel.
%%
api_a_recvfrom_cancel_udp4(suite) ->
    [];
api_a_recvfrom_cancel_udp4(doc) ->
    [];
api_a_recvfrom_cancel_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recvfrom_cancel_udp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvfrom(Sock, 0, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_recv_cancel_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel.
%%
api_a_recvmsg_cancel_udp4(suite) ->
    [];
api_a_recvmsg_cancel_udp4(doc) ->
    [];
api_a_recvmsg_cancel_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recvmsg_cancel_udp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_recv_cancel_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_recv_cancel_udp(InitState) ->
    ServerSeq = 
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind socket (to local address)",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{port => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, local_sa := LSA, port := Port}) ->
                           ServerSA = LSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, SelectInfo} ->
                                   {ok, State#{recv_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await select message (without success)",
           cmd  => fun(#{sock := Sock}) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}}
                           after 5000 ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (no select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, no_select),
                           ok
                   end},
         #{desc => "await continue (cancel)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, cancel)
                   end},
         #{desc => "cancel",
           cmd  => fun(#{sock := Sock, recv_select_info := SelectInfo}) ->
                           ok = socket:cancel(Sock, SelectInfo)
                   end},
         #{desc => "announce ready (cancel)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, cancel),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   State2 = maps:remove(tester,    State),
                                   State3 = maps:remove(recv_stag, State2),
                                   State4 = maps:remove(recv_sref, State3),
                                   State5 = maps:remove(req_src,   State4),
                                   {ok, State5};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           ok = socket:close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    TesterSeq = 
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},

         %% The actual test
         #{desc => "order server continue (recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await server ready (recv select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, recv_select)
                   end},
         #{desc => "await server ready (no select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, no_select)
                   end},
         #{desc => "order server continue (cancel)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, cancel),
                           ok
                   end},
         #{desc => "await server ready (cancel)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, cancel)
                   end},

         %% Terminations
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    ServerInitState = InitState,
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server => Server#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Server, Tester]).





%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make an async (Timeout = nowait) call to accept,
%% wait some time and then cancel.
%%
api_a_accept_cancel_tcp4(suite) ->
    [];
api_a_accept_cancel_tcp4(doc) ->
    [];
api_a_accept_cancel_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_accept_cancel_tcp4,
           fun() ->
                   Accept = fun(Sock) ->
                                    case socket:accept(Sock, nowait) of
                                        {ok, _} = OK ->
                                            OK;
                                        {select, _} = SELECT ->
                                            SELECT;
                                        {error, _} = ERROR ->
                                            ERROR
                                    end
                            end,
                   InitState = #{domain => inet,
                                 accept => Accept},
                   ok = api_a_accept_cancel_tcp(InitState)
           end).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_accept_cancel_tcp(InitState) ->
    process_flag(trap_exit, true),
    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "await connection (nowait)",
           cmd  => fun(#{lsock := LSock, accept := Accept} = State) ->
                           case Accept(LSock) of
                               {select, {select_info, T, R} = SelectInfo} ->
                                   ?SEV_IPRINT("accept select: "
                                               "~n   T: ~p"
                                               "~n   R: ~p", [T, R]),
                                   {ok, State#{accept_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept_select),
                           ok
                   end},
         #{desc => "await select message (without success)",
           cmd  => fun(#{lsock := Sock}) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}}
                           after 5000 ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (no select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, no_select),
                           ok
                   end},
         #{desc => "await continue (cancel)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, cancel)
                   end},
         #{desc => "cancel",
           cmd  => fun(#{lsock := Sock, accept_select_info := SelectInfo}) ->
                           ok = socket:cancel(Sock, SelectInfo)
                   end},
         #{desc => "announce ready (cancel)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, cancel),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{lsock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_port => Port}}
                   end},

         %% *** The actual test ***
         #{desc => "order server to continue (with accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept),
                           ok
                   end},
         #{desc => "await server ready (accept select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, accept_select)
                   end},
         #{desc => "await server ready (no select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, no_select)
                   end},
         #{desc => "order server to continue (cancel)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, cancel),
                           ok
                   end},
         #{desc => "await server ready (cancel)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, cancel)
                   end},

         %% *** Termination ***
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server, State),
                           {ok, State1}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start tester evaluator"),
    TesterInitState = #{server => Server#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, Tester]).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make an async (Timeout = nowait) call to recv,
%% wait some time and then cancel.
%%
api_a_recv_cancel_tcp4(suite) ->
    [];
api_a_recv_cancel_tcp4(doc) ->
    [];
api_a_recv_cancel_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recv_cancel_tcp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recv(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_recv_cancel_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel.
%%
api_a_recvmsg_cancel_tcp4(suite) ->
    [];
api_a_recvmsg_cancel_tcp4(doc) ->
    [];
api_a_recvmsg_cancel_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recvmsg_cancel_tcp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recvmsg(Sock, nowait)
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_recv_cancel_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_recv_cancel_tcp(InitState) ->
    process_flag(trap_exit, true),
    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "await connection (nowait)",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, CSock} ->
                                   {ok, State#{csock => CSock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         #{desc => "await continue (nowait recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{csock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, {select_info, T, R} = SelectInfo} ->
                                   ?SEV_IPRINT("recv select: "
                                               "~n   Tag: ~p"
                                               "~n   Ref: ~p", [T, R]),
                                   {ok, State#{recv_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{csock := Sock}) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}}
                           after 5000 ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (no select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, no_select),
                           ok
                   end},
         #{desc => "await continue (cancel)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, cancel)
                   end},
         #{desc => "cancel",
           cmd  => fun(#{csock := Sock, recv_select_info := SelectInfo}) ->
                           ok = socket:cancel(Sock, SelectInfo)
                   end},
         #{desc => "announce ready (cancel)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, cancel),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close connection socket",
           cmd  => fun(#{csock := Sock}) ->
                           socket:close(Sock)
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{lsock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    ClientSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           {Tester, Port} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, server_port => Port}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** The init part ***
         #{desc => "which server (local) address",
           cmd  => fun(#{domain := Domain, server_port := Port} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           SSA = LSA#{port => Port},
                           {ok, State#{local_sa => LSA, server_sa => SSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect)
                   end},
         #{desc => "connect to server",
           cmd  => fun(#{sock := Sock, server_sa := SSA}) ->
                           socket:connect(Sock, SSA)
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_port => Port}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client := Pid, server_port := Port} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Port),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},

         %% *** The actual test ***
         #{desc => "order server to continue (with accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept),
                           ok
                   end},
         #{desc => "order client to continue (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, client, connect)
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, accept)
                   end},

         #{desc => "order server to continue (recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await server ready (recv select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, recv_select)
                   end},
         #{desc => "await server ready (no select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, no_select)
                   end},
         #{desc => "order server to continue (send request)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, cancel),
                           ok
                   end},
         #{desc => "await server ready (cancel)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, server, cancel)
                   end},

         %% *** Termination ***
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client, State),
                           {ok, State1}
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server, State),
                           {ok, State1}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start client evaluator"),
    Client = ?SEV_START("client", ClientSeq, InitState),

    i("start tester evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make multiple async (Timeout = nowait) call(s) to recvfrom
%% (from *several* processes), wait some time and then cancel.
%% This should result in abort messages to the 'other' processes.
%%
api_a_mrecvfrom_cancel_udp4(suite) ->
    [];
api_a_mrecvfrom_cancel_udp4(doc) ->
    [];
api_a_mrecvfrom_cancel_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecvfrom_cancel_udp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvfrom(Sock, 0, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_mrecv_cancel_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg
%% (from *several* processes), wait some time and then cancel.
%% This should result in abort messages to the 'other' processes.
%%
api_a_mrecvmsg_cancel_udp4(suite) ->
    [];
api_a_mrecvmsg_cancel_udp4(doc) ->
    [];
api_a_mrecvmsg_cancel_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecvmsg_cancel_udp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_mrecv_cancel_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_mrecv_cancel_udp(InitState) ->
    ServerSeq = 
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind socket (to local address)",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{port => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, sock := Sock}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Sock),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, SelectInfo} ->
                                   {ok, State#{recv_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await abort message",
           cmd  => fun(#{sock             := Sock,
                         recv_select_info := {select_info, _, Ref}} = State) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}};
                               {'$socket', Sock, abort, {Ref, closed}} ->
                                   {ok, maps:remove(sock, State)}
                           after 5000 ->
                                   ?SEV_EPRINT("message queue: ~p", [mq()]),
                                   {error, timeout}
                           end
                   end},
         #{desc => "announce ready (abort)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, abort),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   State2 = maps:remove(tester,    State),
                                   State3 = maps:remove(recv_stag, State2),
                                   State4 = maps:remove(recv_sref, State3),
                                   State5 = maps:remove(req_src,   State4),
                                   {ok, State5};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    AltServerSeq = 
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, Sock} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, sock => Sock}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, SelectInfo} ->
                                   {ok, State#{recv_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await abort message",
           cmd  => fun(#{sock             := Sock,
                         recv_select_info := {select_info, _, Ref}} = State) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}};
                               {'$socket', Sock, abort, {Ref, closed}} ->
                                   {ok, maps:remove(sock, State)}
                           after 5000 ->
                                   ?SEV_EPRINT("message queue: ~p", [mq()]),
                                   {error, timeout}
                           end
                   end},
         #{desc => "announce ready (abort)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, abort),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   ?SEV_IPRINT("terminating"),
                                   State1 = maps:remove(recv_select_info, State),
                                   State2 = maps:remove(tester,           State1),
                                   State3 = maps:remove(sock,             State2),
                                   {ok, State3};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],



    TesterSeq = 
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor alt-server 1",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor alt-server 2",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Sock} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{sock => Sock}}
                   end},

         %% Start the alt-server 1
         #{desc => "order alt-server 1 start",
           cmd  => fun(#{alt_server1 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await alt-server 1 ready (init)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, alt_server1, init)
                   end},

         %% Start the alt-server 2
         #{desc => "order alt-server 2 start",
           cmd  => fun(#{alt_server2 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await alt-server 2 ready (init)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, alt_server2, init)
                   end},


         %% The actual test
         #{desc => "order server continue (recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await server ready (recv select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, recv_select)
                   end},

         #{desc => "order alt-server 1 continue (recv)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await alt-server 1 ready (recv select)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server1, recv_select)
                   end},

         #{desc => "order alt-server 2 continue (recv)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await alt-server 2 ready (recv select)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server2, recv_select)
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "close the socket",
           cmd  => fun(#{sock := Sock} = _State) ->
                           socket:close(Sock)
                   end},

         #{desc => "await server ready (abort)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, abort)
                   end},
         #{desc => "await alt-server 1 ready (abort)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server1, abort)
                   end},
         #{desc => "await alt-server 2 ready (abort)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server2, abort)
                   end},

         %% Terminations
         #{desc => "order alt-server 2 to terminate",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await alt-server 2 termination",
           cmd  => fun(#{alt_server2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(alt_server2, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "order alt-server 1 to terminate",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await alt-server 1 termination",
           cmd  => fun(#{alt_server1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(alt_server1, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start alt-server 1 evaluator"),
    AltServer1 = ?SEV_START("alt_server1", AltServerSeq, InitState),

    i("start alt-server 2 evaluator"),
    AltServer2 = ?SEV_START("alt_server2", AltServerSeq, InitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server      => Server#ev.pid,
                        alt_server1 => AltServer1#ev.pid,
                        alt_server2 => AltServer2#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, AltServer1, AltServer2, Tester]).






%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make multiple async (Timeout = nowait) call(s) to accept
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes.
%%
api_a_maccept_cancel_tcp4(suite) ->
    [];
api_a_maccept_cancel_tcp4(doc) ->
    [];
api_a_maccept_cancel_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_maccept_cancel_tcp4,
           fun() ->
                   Accept = fun(Sock) ->
                                    case socket:accept(Sock, nowait) of
                                        {ok, _} = OK ->
                                            OK;
                                        {select, _} = SELECT ->
                                            SELECT;
                                        {error, _} = ERROR ->
                                            ERROR
                                    end
                            end,
                   InitState = #{domain => inet,
                                 accept => Accept},
                   ok = api_a_maccept_cancel_tcp(InitState)
           end).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_maccept_cancel_tcp(InitState) ->
    process_flag(trap_exit, true),
    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lsock := Sock}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Sock),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "await connection (nowait)",
           cmd  => fun(#{lsock := LSock, accept := Accept} = State) ->
                           case Accept(LSock) of
                               {select, {select_info, T, R} = SelectInfo} ->
                                   ?SEV_IPRINT("accept select: "
                                               "~n   T: ~p"
                                               "~n   R: ~p", [T, R]),
                                   {ok, State#{accept_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept_select),
                           ok
                   end},
         #{desc => "await select message (without success)",
           cmd  => fun(#{lsock              := Sock,
                         accept_select_info := {select_info, _, Ref}} = State) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}};
                               {'$socket', Sock, abort, {Ref, closed}} ->
                                   {ok, maps:remove(lsock, State)}
                           after 5000 ->
                                   ?SEV_EPRINT("message queue: ~p", [mq()]),
                                   {error, timeout}
                           end
                   end},
         #{desc => "announce ready (abort)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, abort),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    AltServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, Sock} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, lsock => Sock}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "try accept request (with nowait, expect select)",
           cmd  => fun(#{lsock := Sock, accept := Accept} = State) ->
                           case Accept(Sock) of
                               {select, SelectInfo} ->
                                   {ok, State#{accept_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept_select),
                           ok
                   end},
         #{desc => "await abort message",
           cmd  => fun(#{lsock              := Sock,
                         accept_select_info := {select_info, _, Ref}} = State) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}};
                               {'$socket', Sock, abort, {Ref, closed}} ->
                                   {ok, maps:remove(sock, State)}
                           after 5000 ->
                                   ?SEV_EPRINT("message queue: ~p", [mq()]),
                                   {error, timeout}
                           end
                   end},
         #{desc => "announce ready (abort)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, abort),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   ?SEV_IPRINT("terminating"),
                                   State1 = maps:remove(tester,             State),
                                   State2 = maps:remove(accept_select_info, State1),
                                   State3 = maps:remove(lsock,              State2),
                                   {ok, State3};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor alt-server 1",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor alt-server 2",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Sock} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{sock => Sock}}
                   end},

         %% Start the alt-server 1
         #{desc => "order alt-server 1 start",
           cmd  => fun(#{alt_server1 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await alt-server 1 ready (init)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, alt_server1, init)
                   end},

         %% Start the alt-server 2
         #{desc => "order alt-server 2 start",
           cmd  => fun(#{alt_server2 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await alt-server 2 ready (init)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, alt_server2, init)
                   end},


         %% *** The actual test ***
         #{desc => "order server continue (accept)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         #{desc => "await server ready (accept select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, accept_select)
                   end},

         #{desc => "order alt-server 1 continue (accept)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         #{desc => "await alt-server 1 ready (accept select)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server1, accept_select)
                   end},

         #{desc => "order alt-server 2 continue (accept)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         #{desc => "await alt-server 2 ready (accept select)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server2, accept_select)
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "close the socket",
           cmd  => fun(#{sock := Sock} = _State) ->
                           socket:close(Sock)
                   end},

         #{desc => "await server ready (abort)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, abort)
                   end},
         #{desc => "await alt-server 1 ready (abort)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server1, abort)
                   end},
         #{desc => "await alt-server 2 ready (abort)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server2, abort)
                   end},


         %% *** Termination ***
         #{desc => "order alt-server 2 to terminate",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await alt-server 2 termination",
           cmd  => fun(#{alt_server2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(alt_server2, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "order alt-server 1 to terminate",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await alt-server 1 termination",
           cmd  => fun(#{alt_server1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(alt_server1, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "order server to terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server, State),
                           {ok, State1}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start alt-server 1 evaluator"),
    AltServer1 = ?SEV_START("alt_server1", AltServerSeq, InitState),

    i("start alt-server 2 evaluator"),
    AltServer2 = ?SEV_START("alt_server2", AltServerSeq, InitState),

    i("start tester evaluator"),
    TesterInitState = #{server      => Server#ev.pid,
                        alt_server1 => AltServer1#ev.pid,
                        alt_server2 => AltServer2#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, AltServer1, AltServer2, Tester]).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make multiple async (Timeout = nowait) call(s) to recv
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes.
%%
api_a_mrecv_cancel_tcp4(suite) ->
    [];
api_a_mrecv_cancel_tcp4(doc) ->
    [];
api_a_mrecv_cancel_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecv_cancel_tcp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recv(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_mrecv_cancel_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes.
%%
api_a_mrecvmsg_cancel_tcp4(suite) ->
    [];
api_a_mrecvmsg_cancel_tcp4(doc) ->
    [];
api_a_mrecvmsg_cancel_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecvmsg_cancel_tcp4,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recvmsg(Sock, nowait)
                          end,
                   InitState = #{domain => inet,
                                 recv   => Recv},
                   ok = api_a_mrecv_cancel_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_a_mrecv_cancel_tcp(InitState) ->
    process_flag(trap_exit, true),
    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "await connection (nowait)",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, CSock} ->
                                   {ok, State#{csock => CSock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester, csock := Sock}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept, Sock),
                           ok
                   end},

         #{desc => "await continue (nowait recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{csock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, {select_info, T, R} = SelectInfo} ->
                                   ?SEV_IPRINT("recv select: "
                                               "~n   Tag: ~p"
                                               "~n   Ref: ~p", [T, R]),
                                   {ok, State#{recv_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await select message",
           cmd  => fun(#{csock            := Sock,
                         recv_select_info := {select_info, _, Ref}} = State) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}};
                               {'$socket', Sock, abort, {Ref, closed}} ->
                                   {ok, maps:remove(sock, State)}
                           after 5000 ->
                                   ok
                           end
                   end},
         #{desc => "announce ready (abort)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, abort),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{lsock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    AltServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, Sock} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, sock => Sock}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "try recv request (with nowait, expect select)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock) of
                               {select, SelectInfo} ->
                                   {ok, State#{recv_select_info => SelectInfo}};
                               {ok, X} ->
                                   {error, {unexpected_select_info, X}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv_select)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_select),
                           ok
                   end},
         #{desc => "await abort message",
           cmd  => fun(#{sock             := Sock,
                         recv_select_info := {select_info, _, Ref}} = State) ->
                           receive
                               {'$socket', Sock, select, Ref} ->
                                   {error, {unexpected_select, Ref}};
                               {'$socket', Sock, abort, {Ref, closed}} ->
                                   {ok, maps:remove(sock, State)}
                           after 5000 ->
                                   ?SEV_EPRINT("message queue: ~p", [mq()]),
                                   {error, timeout}
                           end
                   end},
         #{desc => "announce ready (abort)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, abort),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   ?SEV_IPRINT("terminating"),
                                   State1 = maps:remove(recv_select_info, State),
                                   State2 = maps:remove(tester,           State1),
                                   State3 = maps:remove(sock,             State2),
                                   {ok, State3};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           {Tester, Port} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, server_port => Port}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** The init part ***
         #{desc => "which server (local) address",
           cmd  => fun(#{domain := Domain, server_port := Port} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           SSA = LSA#{port => Port},
                           {ok, State#{local_sa => LSA, server_sa => SSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect)
                   end},
         #{desc => "connect to server",
           cmd  => fun(#{sock := Sock, server_sa := SSA}) ->
                           socket:connect(Sock, SSA)
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor alt-server 1",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor alt-server 2",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_port => Port}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client := Pid, server_port := Port} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Port),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},

         #{desc => "order server to continue (with accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept),
                           ok
                   end},
         #{desc => "order client to continue (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, client, connect)
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, Sock} = ?SEV_AWAIT_READY(Pid, server, accept),
                           {ok, State#{sock => Sock}}
                   end},

         %% Start the alt server 1
         #{desc => "order alt-server 1 start",
           cmd  => fun(#{alt_server1 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await alt-server 1 ready (init)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server1, init)
                   end},

         %% Start the alt server 2
         #{desc => "order alt-server 2 start",
           cmd  => fun(#{alt_server2 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await alt-server 2 ready (init)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server2, init)
                   end},


         %% *** The actual test ***
         #{desc => "order server continue (recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await server ready (recv select)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, recv_select)
                   end},

         #{desc => "order alt-server 1 continue (recv)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await alt-server 1 ready (recv select)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server1, recv_select)
                   end},

         #{desc => "order alt-server 2 continue (recv)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await alt-server 2 ready (recv select)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server2, recv_select)
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "close the socket",
           cmd  => fun(#{sock := Sock} = _State) ->
                           socket:close(Sock)
                   end},

         #{desc => "await server ready (abort)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, abort)
                   end},
         #{desc => "await alt-server 1 ready (abort)",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server1, abort)
                   end},
         #{desc => "await alt-server 2 ready (abort)",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, alt_server2, abort)
                   end},

         %% Terminations
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client, State),
                           {ok, State1}
                   end},

         #{desc => "order alt-server 2 to terminate",
           cmd  => fun(#{alt_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await alt-server 2 termination",
           cmd  => fun(#{alt_server2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(alt_server2, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "order alt-server 1 to terminate",
           cmd  => fun(#{alt_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await alt-server 1 termination",
           cmd  => fun(#{alt_server1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(alt_server1, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    Server = ?SEV_START("server", ServerSeq, InitState),

    i("start alt-server 1 evaluator"),
    AltServer1 = ?SEV_START("alt_server1", AltServerSeq, InitState),

    i("start alt-server 2 evaluator"),
    AltServer2 = ?SEV_START("alt_server2", AltServerSeq, InitState),

    i("start client evaluator"),
    Client = ?SEV_START("client", ClientSeq, InitState),

    i("start tester evaluator"),
    TesterInitState = #{server      => Server#ev.pid,
                        alt_server1 => AltServer1#ev.pid,
                        alt_server2 => AltServer2#ev.pid,
                        client      => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, AltServer1, AltServer2, Client, Tester]).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                     %%
%%                           API OPTIONS                               %%
%%                                                                     %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Perform some simple getopt and setopt with the level = otp options
api_opt_simple_otp_options(suite) ->
    [];
api_opt_simple_otp_options(doc) ->
    [];
api_opt_simple_otp_options(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_opt_simple_otp_options,
           fun() -> api_opt_simple_otp_options() end).

api_opt_simple_otp_options() ->
    Get = fun(S, Key) ->
                  socket:getopt(S, otp, Key)
          end,
    Set = fun(S, Key, Val) ->
                  socket:setopt(S, otp, Key, Val)
          end,

    Seq = 
        [
         %% *** Init part ***
         #{desc => "create socket",
           cmd  => fun(#{domain   := Domain, 
                         type     := Type,
                         protocol := Protocol} = State) ->
                           Sock = sock_open(Domain, Type, Protocol),
                           {ok, State#{sock => Sock}}
                   end},
         #{desc => "create dummy process",
           cmd  => fun(State) ->
                           Pid =  spawn_link(fun() -> 
                                                     put(sname, "dummy"),
                                                     receive
                                                         die -> 
                                                             exit(normal) 
                                                     end 
                                             end),
                           {ok, State#{dummy => Pid}}
                   end},

         %% *** Check iow part ***
         #{desc => "get iow",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock, iow) of
                               {ok, IOW} when is_boolean(IOW) ->
                                   {ok, State#{iow => IOW}};
                               {ok, InvalidIOW} ->
                                   {error, {invalid, InvalidIOW}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% #{desc => "enable debug",
         %%   cmd  => fun(#{sock := Sock}) ->
         %%                   ok = socket:setopt(Sock, otp, debug, true)
         %%           end},

         #{desc => "set (new) iow",
           cmd  => fun(#{sock := Sock, iow := OldIOW} = State) ->
                           NewIOW = not OldIOW,
                           case Set(Sock, iow, NewIOW) of
                               ok ->
                                   {ok, State#{iow => NewIOW}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "get (new) iow",
           cmd  => fun(#{sock := Sock, iow := IOW}) ->
                           case Get(Sock, iow) of
                               {ok, IOW} ->
                                   ok;
                               {ok, InvalidIOW} ->
                                   {error, {invalid, InvalidIOW}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** Check rcvbuf part ***
         #{desc => "get rcvbuf",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock, rcvbuf) of
                               {ok, RcvBuf} when is_integer(RcvBuf) ->
                                   {ok, State#{rcvbuf => RcvBuf}};
                               {ok, {N, RcvBuf} = V} when is_integer(N) andalso 
                                                          is_integer(RcvBuf) ->
                                   {ok, State#{rcvbuf => V}};
                               {ok, InvalidRcvBuf} ->
                                   {error, {invalid, InvalidRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "set (new) rcvbuf",
           cmd  => fun(#{sock := Sock, rcvbuf := {OldN, OldRcvBuf}} = State) ->
                           NewRcvBuf = {OldN+2, OldRcvBuf + 1024},
                           case Set(Sock, rcvbuf, NewRcvBuf) of
                               ok ->
                                   {ok, State#{rcvbuf => NewRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{sock := Sock, rcvbuf := OldRcvBuf} = State) when is_integer(OldRcvBuf) ->
                           NewRcvBuf = 2 * OldRcvBuf,
                           case Set(Sock, rcvbuf, NewRcvBuf) of
                               ok ->
                                   {ok, State#{rcvbuf => NewRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{sock := Sock, rcvbuf := OldRcvBuf,
                         type := stream,
                         protocol := tcp} = State) when is_integer(OldRcvBuf) ->
                           NewRcvBuf = {2, OldRcvBuf},
                           case Set(Sock, rcvbuf, NewRcvBuf) of
                               ok ->
                                   {ok, State#{rcvbuf => NewRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "get (new) rcvbuf",
           cmd  => fun(#{sock := Sock, rcvbuf := RcvBuf}) ->
                           case Get(Sock, rcvbuf) of
                               {ok, RcvBuf} ->
                                   ok;
                               {ok, InvalidRcvBuf} ->
                                   {error, {invalid, InvalidRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** Check rcvctrlbuf part ***
         #{desc => "get rcvctrlbuf",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock, rcvctrlbuf) of
                               {ok, RcvCtrlBuf} when is_integer(RcvCtrlBuf) ->
                                   {ok, State#{rcvctrlbuf => RcvCtrlBuf}};
                               {ok, InvalidRcvCtrlBuf} ->
                                   {error, {invalid, InvalidRcvCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "set (new) rcvctrlbuf",
           cmd  => fun(#{sock := Sock, rcvctrlbuf := OldRcvCtrlBuf} = State) ->
                           NewRcvCtrlBuf = 2 * OldRcvCtrlBuf,
                           case Set(Sock, rcvctrlbuf, NewRcvCtrlBuf) of
                               ok ->
                                   {ok, State#{rcvctrlbuf => NewRcvCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "get (new) rcvctrlbuf",
           cmd  => fun(#{sock := Sock, rcvctrlbuf := RcvCtrlBuf}) ->
                           case Get(Sock, rcvctrlbuf) of
                               {ok, RcvCtrlBuf} ->
                                   ok;
                               {ok, InvalidRcvCtrlBuf} ->
                                   {error, {invalid, InvalidRcvCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         %% *** Check rcvctrlbuf part ***
         #{desc => "get rcvctrlbuf",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock, rcvctrlbuf) of
                               {ok, RcvCtrlBuf} when is_integer(RcvCtrlBuf) ->
                                   {ok, State#{rcvctrlbuf => RcvCtrlBuf}};
                               {ok, InvalidRcvCtrlBuf} ->
                                   {error, {invalid, InvalidRcvCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "set (new) rcvctrlbuf",
           cmd  => fun(#{sock := Sock, rcvctrlbuf := OldRcvCtrlBuf} = State) ->
                           NewRcvCtrlBuf = 2 * OldRcvCtrlBuf,
                           case Set(Sock, rcvctrlbuf, NewRcvCtrlBuf) of
                               ok ->
                                   {ok, State#{rcvctrlbuf => NewRcvCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "get (new) rcvctrlbuf",
           cmd  => fun(#{sock := Sock, rcvctrlbuf := RcvCtrlBuf}) ->
                           case Get(Sock, rcvctrlbuf) of
                               {ok, RcvCtrlBuf} ->
                                   ok;
                               {ok, InvalidRcvCtrlBuf} ->
                                   {error, {invalid, InvalidRcvCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** Check sndctrlbuf part ***
         #{desc => "get sndctrlbuf",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock, sndctrlbuf) of
                               {ok, SndCtrlBuf} when is_integer(SndCtrlBuf) ->
                                   {ok, State#{sndctrlbuf => SndCtrlBuf}};
                               {ok, InvalidSndCtrlBuf} ->
                                   {error, {invalid, InvalidSndCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "set (new) sndctrlbuf",
           cmd  => fun(#{sock := Sock, sndctrlbuf := OldSndCtrlBuf} = State) ->
                           NewSndCtrlBuf = 2 * OldSndCtrlBuf,
                           case Set(Sock, sndctrlbuf, NewSndCtrlBuf) of
                               ok ->
                                   {ok, State#{sndctrlbuf => NewSndCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "get (new) sndctrlbuf",
           cmd  => fun(#{sock := Sock, sndctrlbuf := SndCtrlBuf}) ->
                           case Get(Sock, sndctrlbuf) of
                               {ok, SndCtrlBuf} ->
                                   ok;
                               {ok, InvalidSndCtrlBuf} ->
                                   {error, {invalid, InvalidSndCtrlBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** Check controlling-process part ***
         #{desc => "verify self as controlling-process",
           cmd  => fun(#{sock := Sock}) ->
                           Self = self(),
                           case Get(Sock, controlling_process) of
                               {ok, Self} ->
                                   ok;
                               {ok, InvalidPid} ->
                                   {error, {invalid, InvalidPid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "set dummy as controlling-process",
           cmd  => fun(#{sock := Sock, dummy := Dummy}) ->
                           Set(Sock, controlling_process, Dummy)
                   end},
         #{desc => "verify dummy as controlling-process",
           cmd  => fun(#{sock := Sock, dummy := Dummy}) ->
                           case Get(Sock, controlling_process) of
                               {ok, Dummy} ->
                                   ok;
                               {ok, InvalidPid} ->
                                   {error, {invalid, InvalidPid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         #{desc => "finish",
           cmd  => fun(_) ->
                           {ok, normal}
                   end}
        ],

    i("start tcp (stream) evaluator"),
    InitState1 = #{domain => inet, type => stream, protocol => tcp},
    Tester1 = ?SEV_START("tcp-tester", Seq, InitState1),
    i("await tcp evaluator"),
    ok = ?SEV_AWAIT_FINISH([Tester1]),

    i("start udp (dgram) socket"),
    InitState2 = #{domain => inet, type => dgram, protocol => udp},
    Tester2 = ?SEV_START("udp-tester", Seq, InitState2),
    i("await udp evaluator"),
    ok = ?SEV_AWAIT_FINISH([Tester2]).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Perform some simple operations with the rcvbuf otp option
%% The operations we test here are only for type = stream and
%% protocol = tcp.
api_opt_simple_otp_rcvbuf_option(suite) ->
    [];
api_opt_simple_otp_rcvbuf_option(doc) ->
    [];
api_opt_simple_otp_rcvbuf_option(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(api_opt_simple_otp_rcvbuf_option,
           fun() -> api_opt_simple_otp_rcvbuf_option() end).

api_opt_simple_otp_rcvbuf_option() ->
    Get = fun(S) ->
                  socket:getopt(S, otp, rcvbuf)
          end,
    Set = fun(S, Val) ->
                  socket:setopt(S, otp, rcvbuf, Val)
          end,

    ServerSeq = 
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester   := Tester,
                         local_sa := LocalSA,
                         lport    := Port}) ->
                           ServerSA = LocalSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},


         %% *** The actual test part ***
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "attempt to accept",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         %% Recv with default size for (otp) rcvbuf
         #{desc => "await continue (recv initial)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of
                               {ok, MsgSz} ->
                                   ?SEV_IPRINT("MsgSz: ~p", [MsgSz]),
                                   {ok, State#{msg_sz => MsgSz}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to recv",
           cmd  => fun(#{sock := Sock, msg_sz := MsgSz} = _State) ->
                           ?SEV_IPRINT("try recv ~w bytes when rcvbuf is ~s", 
                                       [MsgSz,
                                        case Get(Sock) of
                                            {ok, RcvBuf} -> f("~w", [RcvBuf]);
                                            {error, _}   -> "-"
                                        end]),
                           case socket:recv(Sock) of
                               {ok, Data} when (size(Data) =:= MsgSz) ->
                                   ok;
                               {ok, Data} ->
                                   {error, {invalid_msg_sz, MsgSz, size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv initial)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv),
                           ok
                   end},

         %% Recv with new size (1) for (otp) rcvbuf
         #{desc => "await continue (recv 1)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of
                               {ok, NewRcvBuf} ->
                                   ?SEV_IPRINT("set new rcvbuf: ~p", [NewRcvBuf]),
                                   {ok, State#{rcvbuf => NewRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to setopt rcvbuf",
           cmd  => fun(#{sock := Sock, rcvbuf := NewRcvBuf} = _State) ->
                           case Set(Sock, NewRcvBuf) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to recv",
           cmd  => fun(#{sock := Sock, msg_sz := MsgSz} = _State) ->
                           case socket:recv(Sock) of
                               {ok, Data} when (size(Data) =:= MsgSz) ->
                                   ok;
                               {ok, Data} ->
                                   {error, {invalid_msg_sz, MsgSz, size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv),
                           ok
                   end},

         %% Recv with new size (2) for (otp) rcvbuf
         #{desc => "await continue (recv 2)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of
                               {ok, NewRcvBuf} ->
                                   ?SEV_IPRINT("set new rcvbuf: ~p", [NewRcvBuf]),
                                   {ok, State#{rcvbuf => NewRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to setopt rcvbuf",
           cmd  => fun(#{sock := Sock, rcvbuf := NewRcvBuf} = _State) ->
                           case Set(Sock, NewRcvBuf) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to recv",
           cmd  => fun(#{sock := Sock, msg_sz := MsgSz} = _State) ->
                           case socket:recv(Sock) of
                               {ok, Data} when (size(Data) =:= MsgSz) ->
                                   ok;
                               {ok, Data} ->
                                   {error, {invalid_msg_sz, MsgSz, size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv),
                           ok
                   end},

         %% Recv with new size (3) for (otp) rcvbuf
         #{desc => "await continue (recv 3, truncated)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of
                               {ok, {ExpSz, NewRcvBuf}} ->
                                   {ok, State#{msg_sz => ExpSz,
                                               rcvbuf => NewRcvBuf}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to setopt rcvbuf",
           cmd  => fun(#{sock := Sock, rcvbuf := NewRcvBuf} = _State) ->
                           case Set(Sock, NewRcvBuf) of
                               ok ->
                                   ?SEV_IPRINT("set new rcvbuf: ~p", [NewRcvBuf]),
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to recv",
           cmd  => fun(#{sock := Sock, msg_sz := MsgSz} = _State) ->
                           ?SEV_IPRINT("try recv ~w bytes of data", [MsgSz]),
                           case socket:recv(Sock) of
                               {ok, Data} when (size(Data) =:= MsgSz) ->
                                   ok;
                               {ok, Data} ->
                                   {error, {invalid_msg_sz, MsgSz, size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv),
                           ok
                   end},


         %% Termination
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket(s)",
           cmd  => fun(#{lsock := LSock, sock := Sock} = State) ->
                           sock_close(Sock),
                           sock_close(LSock),
                           State1 = maps:remove(sock,  State),
                           State2 = maps:remove(lport, State1),
                           State3 = maps:remove(lsock, State2),
                           {ok, State3}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, ServerSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester,
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect)
                   end},
         #{desc => "connect to server",
           cmd  => fun(#{sock := Sock, server_sa := SSA}) ->
                           socket:connect(Sock, SSA)
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         #{desc => "await continue (send initial)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, send) of
                               {ok, Data} ->
                                   {ok, State#{data => Data}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "send (initial) data to server",
           cmd  => fun(#{sock := Sock, data := Data} = _State) ->
                           ?SEV_IPRINT("try send ~w bytes", [size(Data)]),
                           socket:send(Sock, Data)
                   end},
         #{desc => "announce ready (send initial)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send),
                           ok
                   end},

         #{desc => "await continue (send 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send)
                   end},
         #{desc => "send (1) data to server",
           cmd  => fun(#{sock := Sock, data := Data}) ->
                           ?SEV_IPRINT("try send ~w bytes", [size(Data)]),
                           socket:send(Sock, Data)
                   end},
         #{desc => "announce ready (send 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send),
                           ok
                   end},

         #{desc => "await continue (send 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send)
                   end},
         #{desc => "send (2) data to server",
           cmd  => fun(#{sock := Sock, data := Data}) ->
                           ?SEV_IPRINT("try send ~w bytes", [size(Data)]),
                           socket:send(Sock, Data)
                   end},
         #{desc => "announce ready (send 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send),
                           ok
                   end},

         #{desc => "await continue (send 3)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send)
                   end},
         #{desc => "send (3) data to server",
           cmd  => fun(#{sock := Sock, data := Data}) ->
                           ?SEV_IPRINT("try send ~w bytes", [size(Data)]),
                           socket:send(Sock, Data)
                   end},
         #{desc => "announce ready (send 3)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send),
                           ok
                   end},


         %% Termination
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock}) ->
                           socket:close(Sock)
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Server} = _State) ->
                           _MRef = erlang:monitor(process, Server),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Client} = _State) ->
                           _MRef = erlang:monitor(process, Client),
                           ok
                   end},
         #{desc => "order server start",
           cmd  => fun(#{server := Server}) ->
                           ?SEV_ANNOUNCE_START(Server)
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Server} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Server, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},
         #{desc => "order client start",
           cmd  => fun(#{client    := Client,
                         server_sa := ServerSA}) ->
                           ?SEV_ANNOUNCE_START(Client, ServerSA),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, init)
                   end},


         %% The actual test (connecting)
         #{desc => "order server accept (accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (connect)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, connect),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, connect)
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept)
                   end},

         %% The actual test (initial part)
         #{desc => "order client continue (send initial)",
           cmd  => fun(#{client := Client, data := Data} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Data),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order server continue (recv initial)",
           cmd  => fun(#{server := Server, data := Data} = _State) ->
                           ExpMsgSz = size(Data),
                           ?SEV_ANNOUNCE_CONTINUE(Server, recv, ExpMsgSz),
                           ok
                   end},
         #{desc => "await client ready (send initial)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, client, send,
                                                 [{server, Server}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await server ready (recv initial)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Server, client, recv,
                                                 [{client, Client}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% The actual test (part 1)
         #{desc => "order client continue (send 1)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order server continue (recv 1)",
           cmd  => fun(#{server := Server, data := Data} = _State) ->
                           MsgSz     = size(Data),
                           NewRcvBuf = {2 + (MsgSz div 1024), 1024},
                           ?SEV_ANNOUNCE_CONTINUE(Server, recv, NewRcvBuf),
                           ok
                   end},
         #{desc => "await client ready (send 1)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, client, send,
                                                 [{server, Server}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await server ready (recv 1)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Server, client, recv,
                                                 [{client, Client}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% The actual test (part 2)
         #{desc => "order client continue (send 2)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order server continue (recv 2)",
           cmd  => fun(#{server := Server, data := Data} = _State) ->
                           MsgSz     = size(Data),
                           NewRcvBuf = {2 + (MsgSz div 2048), 2048},
                           ?SEV_ANNOUNCE_CONTINUE(Server, recv, NewRcvBuf),
                           ok
                   end},
         #{desc => "await client ready (send 2)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, client, send,
                                                 [{server, Server}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await server ready (recv 2)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Server, client, recv,
                                                 [{client, Client}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% The actual test (part 3)
         #{desc => "order client continue (send 3)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order server continue (recv 3)",
           cmd  => fun(#{server := Server, data := Data} = _State) ->
                           MsgSz     = size(Data),
                           BufSz     = 2048,
                           N         = MsgSz div BufSz - 1,
                           NewRcvBuf = {N, BufSz},
                           ?SEV_ANNOUNCE_CONTINUE(Server, recv,
                                                  {N*BufSz, NewRcvBuf})
                   end},
         #{desc => "await client ready (send 3)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, client, send,
                                                 [{server, Server}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await server ready (recv 3)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Server, client, recv,
                                                 [{client, Client}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         ?SEV_SLEEP(?SECS(1)),

         %% *** Terminate server ***
         #{desc => "order client terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client down",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client,    State),
                           {ok, State1}
                   end},
         #{desc => "order server terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server down",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server,    State),
                           State2 = maps:remove(server_sa, State1),
                           {ok, State2}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    %% Create a data binary of 6*1024 bytes
    Data      = list_to_binary(lists:duplicate(6*4, lists:seq(0, 255))),
    InitState = #{domain => inet,
                  data   => Data},

    i("create server evaluator"),
    ServerInitState = #{domain => maps:get(domain, InitState)},
    Server          = ?SEV_START("server", ServerSeq, ServerInitState),

    i("create client evaluator"),
    ClientInitState = #{host   => local_host(),
                        domain => maps:get(domain, InitState)},
    Client          = ?SEV_START("client", ClientSeq, ClientInitState),

    i("create tester evaluator"),
    TesterInitState = InitState#{server => Server#ev.pid,
                                 client => Client#ev.pid},
    Tester          = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Perform some simple getopt and setopt with the level = otp options
api_opt_simple_otp_controlling_process(suite) ->
    [];
api_opt_simple_otp_controlling_process(doc) ->
    [];
api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(api_opt_simple_otp_controlling_process,
           fun() -> api_opt_simple_otp_controlling_process() end).

api_opt_simple_otp_controlling_process() ->
    Get = fun(S, Key) ->
                  socket:getopt(S, otp, Key)
          end,
    Set = fun(S, Key, Val) ->
                  socket:setopt(S, otp, Key, Val)
          end,

    ClientSeq =
        [
         %% *** Init part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, Sock} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester,
                                       sock   => Sock}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "verify tester as controlling-process",
           cmd  => fun(#{tester := Tester, sock := Sock} = _State) ->
                           case Get(Sock, controlling_process) of
                               {ok, Tester} ->
                                   ok;
                               {ok, InvalidPid} ->
                                   {error, {invalid, InvalidPid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt invalid controlling-process transfer (to self)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case Set(Sock, controlling_process, self()) of
                               {error, not_owner} ->
                                   ok;
                               ok ->
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (not owner)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, not_owner),
                           ok
                   end},
         #{desc => "await continue (owner)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, owner)
                   end},
         #{desc => "verify self as controlling-process",
           cmd  => fun(#{sock := Sock} = _State) ->
                           Self = self(),
                           case Get(Sock, controlling_process) of
                               {ok, Self} ->
                                   ok;
                               {ok, InvalidPid} ->
                                   {error, {invalid, InvalidPid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt controlling-process transfer to tester",
           cmd  => fun(#{tester := Tester, sock := Sock} = _State) ->
                           Set(Sock, controlling_process, Tester)
                   end},
         #{desc => "attempt invalid controlling-process transfer (to self)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case Set(Sock, controlling_process, self()) of
                               {error, not_owner} ->
                                   ok;
                               ok ->
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (owner)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, owner),
                           ok

                   end},
         
         %% *** Termination ***
         #{desc => "await termination",
           cmd  => fun(#{tester := Tester} = State) ->
                           ?SEV_AWAIT_TERMINATE(Tester, tester),
                           State1 = maps:remove(tester, State),
                           State2 = maps:remove(sock, State1),
                           {ok, State2}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "create socket",
           cmd  => fun(#{domain   := Domain, 
                         type     := Type,
                         protocol := Protocol} = State) ->
                           Sock = sock_open(Domain, Type, Protocol),
                           {ok, State#{sock => Sock}}
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Client} = _State) ->
                           _MRef = erlang:monitor(process, Client),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "verify self as controlling-process",
           cmd  => fun(#{sock := Sock} = _State) ->
                           Self = self(),
                           case Get(Sock, controlling_process) of
                               {ok, Self} ->
                                   ok;
                               {ok, InvalidPid} ->
                                   {error, {invalid, InvalidPid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order (client) start",
           cmd  => fun(#{client := Client, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Client, Sock),
                           ok
                   end},
         #{desc => "await (client) ready (not owner)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, not_owner)
                   end},
         #{desc => "attempt controlling-process transfer to client",
           cmd  => fun(#{client := Client, sock := Sock} = _State) ->
                           Set(Sock, controlling_process, Client)
                   end},
         #{desc => "verify client as controlling-process",
           cmd  => fun(#{client := Client, sock := Sock} = _State) ->
                           case Get(Sock, controlling_process) of
                               {ok, Client} ->
                                   ok;
                               {ok, InvalidPid} ->
                                   {error, {invalid, InvalidPid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt invalid controlling-process transfer (to self)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case Set(Sock, controlling_process, self()) of
                               {error, not_owner} ->
                                   ok;
                               ok ->
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order (client) continue (owner)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, owner),
                           ok
                   end},
         #{desc => "await (client) ready (2)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, owner),
                           ok
                   end},
         #{desc => "verify self as controlling-process",
           cmd  => fun(#{sock := Sock} = _State) ->
                           Self = self(),
                           case Get(Sock, controlling_process) of
                               {ok, Self} ->
                                   ok;
                               {ok, InvalidPid} ->
                                   {error, {invalid, InvalidPid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** Termination ***
         #{desc => "order (client) terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           {ok, maps:remove(client, State)}
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           sock_close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start tcp (stream) client evaluator"),
    ClientInitState1 = #{},
    Client1 = ?SEV_START("tcp-client", ClientSeq, ClientInitState1),

    i("start tcp (stream) tester evaluator"),
    TesterInitState1 = #{domain   => inet, 
                         type     => stream, 
                         protocol => tcp,
                         client   => Client1#ev.pid},
    Tester1 = ?SEV_START("tcp-tester", TesterSeq, TesterInitState1),

    i("await tcp evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Tester1, Client1]),

    i("start udp (dgram) client evaluator"),
    ClientInitState2 = #{},
    Client2 = ?SEV_START("udp-client", ClientSeq, ClientInitState2),

    i("start udp (dgram) tester evaluator"),
    TesterInitState2 = #{domain   => inet, 
                         type     => dgram, 
                         protocol => udp,
                         client   => Client2#ev.pid},
    Tester2 = ?SEV_START("udp-tester", TesterSeq, TesterInitState2),

    i("await udp evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Tester2, Client2]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Tests that the add_mambership and drop_membership ip options work.
%% We create one server and two clients. The server only send messages,
%% the clients only receives messages.
%% An UDP datagram is forbidden (RFC 1122) from having a source address
%% that is a multicast address (or a broadcast address).
%% So, the server create a socket "for sending" and the clients sockets
%% "for receiving".
%% Sending socket:   Bound to the local address (and any port).
%%                   When sending, the dest will be the multicast address
%%                   and port of the receiving socket.
%% Receiving socket: Bound to the multicast address and port.
api_opt_ip_add_drop_membership(suite) ->
    [];
api_opt_ip_add_drop_membership(doc) ->
    ["OTP-15908 (ERL-980)"];
api_opt_ip_add_drop_membership(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(api_opt_ip_add_drop_membership,
           fun() ->
                   has_ip_add_membership_support(),
                   has_ip_drop_membership_support(),
                   has_ip_multicast_support()
           end,
           fun() -> api_opt_ip_add_drop_membership() end).


api_opt_ip_add_drop_membership() ->
    Set = fun(S, Key, Val) ->
                  socket:setopt(S, ip, Key, Val)
          end,
    AddMembership  = fun(S, Val) -> Set(S, add_membership,  Val) end,
    DropMembership = fun(S, Val) -> Set(S, drop_membership, Val) end,

    ServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, MSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, msa => MSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make recv socket reuse addr",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case socket:setopt(Sock, socket, reuseaddr, true) of
                               ok ->
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Failed set reuseaddr: "
                                               "~n   ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "bind recv socket to multicast address",
           cmd  => fun(#{sock := Sock, msa := MSA} = State) ->
                           case socket:bind(Sock, MSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("bound to:"
                                               "~n   ~p", [Port]),
                                   {ok, State#{msa => MSA#{port => Port}}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (add_membership)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, add_membership)
                   end},
         #{desc => "add membership",
           cmd  => fun(#{sock     := Sock,
                         msa      := #{addr := MAddr},
                         local_sa := #{addr := Addr}} = State) ->
                           MReq = #{multiaddr => MAddr,
                                    interface => Addr},
                           ?SEV_IPRINT("try add membership to:"
                                       "~n   ~p", [MReq]),
                           case AddMembership(Sock, MReq) of
                               ok ->
                                   ?SEV_IPRINT("membership added"),
                                   {ok, State#{mreq => MReq}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Failed adding membership to: "
                                               "~n   ~p"
                                               "~n   Reason:  ~p",
                                               [MReq, Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (add-membership)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, add_membership),
                           ok
                   end},

         #{desc => "await continue (drop_membership)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, drop_membership)
                   end},
         #{desc => "drop membership",
           cmd  => fun(#{sock := Sock,
                         mreq := MReq} = State) ->
                           ?SEV_IPRINT("try drop membership from:"
                                       "~n   ~p", [MReq]),
                           case DropMembership(Sock, MReq) of
                               ok ->
                                   ?SEV_IPRINT("membership dropped"),
                                   {ok, maps:remove(mreq, State)};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Failed drop membership from: "
                                               "~n   ~p"
                                               "~n   Reason:  ~p",
                                               [MReq, Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (drop-membership)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, drop_membership),
                           ok
                   end},


         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           socket:close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Server} = _State) ->
                           _MRef = erlang:monitor(process, Server),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid, msa := MSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, MSA),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = _State) ->
                           case ?SEV_AWAIT_READY(Pid, server, init) of
                               ok ->
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Start of server failed: "
                                               "~n   ~p", [Reason]),
                                   ERROR
                           end
                   end},


         %% *** The actual test ***
         #{desc => "order server to continue (add-membership)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, add_membership),
                           ok
                   end},
         #{desc => "await server ready (add-membership)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, add_membership)
                   end},

         #{desc => "order server to continue (drop-membership)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, drop_membership),
                           ok
                   end},
         #{desc => "await server ready (drop-membership)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, drop_membership)
                   end},

         ?SEV_SLEEP(?SECS(1)),

         %% *** Termination ***
         #{desc => "order server terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           {ok, maps:remove(server, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    i("get multicast address"),
    Domain = inet,
    MAddr  = which_ip_multicast_address(),
    MSA    = #{family => Domain, addr => MAddr},

    i("start server evaluator"),
    ServerInitState = #{domain => Domain},
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start tester evaluator"),
    TesterInitState = #{domain  => Domain,
                        msa     => MSA,
                        server  => Server#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Tester, Server]).



which_ip_multicast_address() ->
    which_multicast_address(inet).

which_multicast_address(Domain) ->
    case os:type() of
        {unix, linux} ->
            WhichMAddr = fun([_, _, MAddr]) -> MAddr end,
            which_multicast_address2(Domain, WhichMAddr);

        {unix, sunos} ->
            WhichMAddr = fun([_, MAddr, _]) -> MAddr end,
            which_multicast_address2(Domain, WhichMAddr);

        Type ->
            not_supported({multicast, Type})
    end.

%% Note that the 'netstat -g' table looks different on linux and SunOS
%% Linux: IfName - RefCnt - Group
%% SunOS: IfName - Group  - RefCnt

which_multicast_address2(Domain, WhichMAddr) ->
    IfName           = which_local_host_ifname(Domain),
    NetstatGroupsStr = os:cmd("netstat -g | grep " ++ IfName),
    NetstatGroups0   = string:tokens(NetstatGroupsStr, [$\n]),
    NetstatGroups    = [string:tokens(G, [$ ]) || G <- NetstatGroups0],
    MAddrs           = [WhichMAddr(NetstatGroup) || NetstatGroup <-
                                                        NetstatGroups],
    which_multicast_address3(Domain, MAddrs).

which_multicast_address3(_Domain, []) ->
    not_supported({multicast, no_valid_addrs});
which_multicast_address3(Domain, [MAddrStr|MAddrs]) ->
    %% Even on linux some of these are not actually addresses, but
    %% "host names", such as all-systems.mcast.net. But both
    %% address strings, such as "224.0.0.251" and host name strings
    %% gets translated into an address by the inet:inet:getaddr/2.
    case inet:getaddr(MAddrStr, Domain) of
        {ok, MAddr} ->
            MAddr;
        {error, _} ->
            which_multicast_address3(Domain, MAddrs)
    end.
    
which_local_host_ifname(Domain) ->
    case which_local_host_info(Domain) of
        {ok, {Name, _Addr, _Flags}} ->
            Name;
        {error, Reason} ->
            not_supported({multicast, Reason})
    end.

    

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                     %%
%%                  API OPERATIONS WITH TIMEOUT                        %%
%%                                                                     %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the connect timeout option
%% on an IPv4 TCP (stream) socket.
api_to_connect_tcp4(suite) ->
    [];
api_to_connect_tcp4(doc) ->
    [];
api_to_connect_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    Cond = fun() -> api_to_connect_cond() end,
    tc_try(api_to_connect_tcp4,
           Cond,
           fun() ->
                   InitState = #{domain        => inet,
                                 backlog       => 1,
                                 timeout       => 5000,
                                 connect_limit => 3},
                   ok = api_to_connect_tcp(InitState)
           end).

api_to_connect_cond() ->
    api_to_connect_cond(os:type(), os:version()).

%% I don't know exactly at which version this starts to work.
%% I know it does not work for 4.4.*, but is does for 4.15.
%% So, just to simplify, we require atleast 4.15
api_to_connect_cond({unix, linux}, {Maj, Min, _Rev}) ->
    if
        (Maj > 4) ->
            ok;
        ((Maj =:= 4) andalso (Min >= 15)) ->
            ok;
        true ->
            skip("TC does not work")
    end;
%% Only test on one machine, which has version 6.3, and there it does
%% not work, so disable for all.
api_to_connect_cond({unix, openbsd}, _) ->
    skip("TC does not work");
api_to_connect_cond({unix, freebsd}, {Maj, Min, _Rev}) ->
    if
        ((Maj >= 10) andalso (Min >= 4)) ->
            ok;
        true ->
            skip("TC may not work")
    end;
api_to_connect_cond({unix, sunos}, {Maj, Min, _Rev}) ->
    if
        ((Maj >= 5) andalso (Min >= 10)) ->
            ok;
        true ->
            skip("TC may not work")
    end;
api_to_connect_cond(_, _) ->
    skip("TC may not work").



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the connect timeout option
%% on an IPv6 TCP (stream) socket.
api_to_connect_tcp6(suite) ->
    [];
api_to_connect_tcp6(doc) ->
    [];
api_to_connect_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_connect_tcp6,
           fun() -> has_support_ipv6(), api_to_connect_cond() end,
           fun() ->
                   InitState = #{domain        => inet6,
                                 backlog       => 1,
                                 timeout       => 5000,
                                 connect_limit => 3},
                   ok = api_to_connect_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% We use the backlog (listen) argument to test this.
%% Note that the behaviour of the TCP "server side" can vary when 
%% a client connect to a "busy" server (full backlog).
%% For instance, on FreeBSD (11.2) the reponse when the backlog is full
%% is a econreset.

api_to_connect_tcp(InitState) ->
    process_flag(trap_exit, true),

    ServerSeq = 
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           {Tester, Backlog} = ?SEV_AWAIT_START(),
                           {ok, State#{tester  => Tester,
                                       backlog => Backlog}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket (with backlog = 1)",
           cmd  => fun(#{lsock := LSock, backlog := Backlog}) ->
                           socket:listen(LSock, Backlog)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{lsock := Sock} = State) ->
                           sock_close(Sock),
                           State1 = maps:remove(lport, State),
                           State2 = maps:remove(sock,  State1),
                           {ok, State2}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, ServerSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester,
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create node",
           cmd  => fun(#{host := Host} = State) ->
			   ?SEV_IPRINT("try create node on ~p", [Host]),
                           case start_node(Host, client) of
                               {ok, Node} ->
                                   ?SEV_IPRINT("client node ~p started",
                                               [Node]),
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor client node",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "start remote client on client node",
           cmd  => fun(#{node := Node} = State) ->
                           Pid = api_toc_tcp_client_start(Node),
                           ?SEV_IPRINT("remote client ~p started", [Pid]),
                           {ok, State#{rclient => Pid}}
                   end},
         #{desc => "monitor remote client",
           cmd  => fun(#{rclient := Pid}) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "order remote client to start",
           cmd  => fun(#{rclient   := Client,
                         server_sa := ServerSA}) ->
                           ?SEV_ANNOUNCE_START(Client, ServerSA),
                           ok
                   end},
         #{desc => "await remote client ready",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, init,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, connect,
                                                    [{rclient, Client}]) of
                               {ok, {ConTimeout, ConLimit}} ->
                                   {ok, State#{connect_timeout => ConTimeout,
                                               connect_limit   => ConLimit}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (connect)",
           cmd  => fun(#{rclient         := RClient,
                         connect_timeout := ConTimeout,
                         connect_limit   := ConLimit}) ->
                           ?SEV_ANNOUNCE_CONTINUE(RClient, connect,
                                                  {ConTimeout, ConLimit}),
                           ok
                   end},
         #{desc => "await remote client ready (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = State) ->
                           case ?SEV_AWAIT_READY(RClient, rclient, connect,
                                                 [{tester, Tester}]) of
                               {ok, ok = _Result} ->
                                   {ok, maps:remove(connect_limit, State)};
                               {ok, {error, {connect_limit_reached,R,L}}} ->
                                   {skip,
                                    ?LIB:f("Connect limit reached ~w: ~w",
                                           [L, R])};
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester,
                                                     [{rclient, RClient}]) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "kill remote client",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await remote client termination",
           cmd  => fun(#{rclient := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(rclient, State),
                           {ok, State1}
                   end},
         #{desc => "stop client node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await client node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   State1 = maps:remove(node_id, State),
                                   State2 = maps:remove(node,    State1),
                                   {ok, State2}
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Server} = _State) ->
                           _MRef = erlang:monitor(process, Server),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Client} = _State) ->
                           _MRef = erlang:monitor(process, Client),
                           ok
                   end},
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "order server start",
           cmd  => fun(#{server  := Server,
                         backlog := Backlog}) ->
                           ?SEV_ANNOUNCE_START(Server, Backlog),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Server, local_sa := LSA} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Server, server, init),
                           ServerSA = LSA#{port => Port},
                           {ok, State#{server_sa => ServerSA}}
                   end},
         #{desc => "order client start",
           cmd  => fun(#{client    := Client,
                         server_sa := ServerSA}) ->
                           ?SEV_ANNOUNCE_START(Client, ServerSA),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, init),
                           ok
                   end},

         %% The actual test
         %% The server does nothing (this is the point), no accept,
         %% the client tries to connect.
         #{desc => "order client continue (connect)",
           cmd  => fun(#{client        := Client,
                         timeout       := Timeout,
                         connect_limit := ConLimit} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, connect,
                                                  {Timeout, ConLimit}),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, client, connect,
                                                 [{server, Server}]) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** Terminate server ***
         #{desc => "order client terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client down",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client,    State),
                           {ok, State1}
                   end},
         #{desc => "order server terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server down",
           cmd  => fun(#{server := Server} = State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           State1 = maps:remove(server,    State),
                           State2 = maps:remove(server_sa, State1),
                           {ok, State2}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("create server evaluator"),
    ServerInitState = #{domain => maps:get(domain, InitState)},
    Server          = ?SEV_START("server", ServerSeq, ServerInitState),

    i("create client evaluator"),
    ClientInitState = #{host   => local_host(),
                        domain => maps:get(domain, InitState)},
    Client          = ?SEV_START("client", ClientSeq, ClientInitState),

    i("create tester evaluator"),
    TesterInitState = InitState#{server => Server#ev.pid,
                                 client => Client#ev.pid},
    Tester          = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).


api_toc_tcp_client_start(Node) ->
    Self = self(),
    Fun  = fun() -> api_toc_tcp_client(Self) end,
    erlang:spawn(Node, Fun).

api_toc_tcp_client(Parent) ->
    api_toc_tcp_client_init(Parent),
    ServerSA = api_toc_tcp_client_await_start(Parent),
    Domain   = maps:get(family, ServerSA),
    api_toc_tcp_client_announce_ready(Parent, init),
    {To, ConLimit} = api_toc_tcp_client_await_continue(Parent, connect),
    Result = api_to_connect_tcp_await_timeout(To, ServerSA, Domain, ConLimit),
    ?SEV_IPRINT("result: ~p", [Result]),
    api_toc_tcp_client_announce_ready(Parent, connect, Result),
    Reason = api_toc_tcp_client_await_terminate(Parent),
    exit(Reason).

api_toc_tcp_client_init(Parent) ->
    put(sname, "rclient"),
    %% i("api_toc_tcp_client_init -> entry"),
    _MRef = erlang:monitor(process, Parent),
    ok.

api_toc_tcp_client_await_start(Parent) ->
    %% i("api_toc_tcp_client_await_start -> entry"),
    ?SEV_AWAIT_START(Parent).

api_toc_tcp_client_announce_ready(Parent, Slogan) ->
    ?SEV_ANNOUNCE_READY(Parent, Slogan).
api_toc_tcp_client_announce_ready(Parent, Slogan, Result) ->
    ?SEV_ANNOUNCE_READY(Parent, Slogan, Result).

api_toc_tcp_client_await_continue(Parent, Slogan) ->
    %% i("api_toc_tcp_client_await_continue -> entry"),
    case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of
        ok ->
            ok;
        {ok, Extra} ->
            Extra;
        {error, Reason} ->
            exit({await_continue, Slogan, Reason})
    end.

api_toc_tcp_client_await_terminate(Parent) ->
    %% i("api_toc_tcp_client_await_terminate -> entry"),
    case ?SEV_AWAIT_TERMINATE(Parent, parent) of
        ok ->
            ok;
        {error, Reason} ->
            Reason
    end.

api_to_connect_tcp_await_timeout(To, ServerSA, Domain, ConLimit) ->
    LSA = which_local_socket_addr(Domain),
    NewSock = fun() ->
                      S = case socket:open(Domain, stream, tcp) of
                              {ok, Sock} ->
                                  Sock;
                              {error, OReason} ->
                                  ?FAIL({open, OReason})
                          end,
                      case socket:bind(S, LSA) of
                          {ok, _} ->
                              S;
                          {error, BReason} ->
                              ?FAIL({bind, BReason})
                      end
              end,
    api_to_connect_tcp_await_timeout(1, ConLimit, To, ServerSA, NewSock, []).

api_to_connect_tcp_await_timeout(ID, ConLimit, _To, _ServerSA, _NewSock, Acc)
  when (ID > ConLimit) ->
    api_to_connect_tcp_await_timeout3(Acc),
    {error, {connect_limit_reached, ID, ConLimit}};
api_to_connect_tcp_await_timeout(ID, ConLimit, To, ServerSA, NewSock, Acc) ->
    case api_to_connect_tcp_await_timeout2(ID, To, ServerSA, NewSock) of
        ok ->
            %% ?SEV_IPRINT("success when number of socks: ~w", [length(Acc)]),
            api_to_connect_tcp_await_timeout3(Acc),
            ok;
        {ok, Sock} ->
            %% ?SEV_IPRINT("~w: unexpected success (connect)", [ID]),
            api_to_connect_tcp_await_timeout(ID+1, ConLimit,
                                             To, ServerSA, NewSock,
                                             [Sock|Acc]);
        {error, _} = ERROR ->
            ERROR
    end.

api_to_connect_tcp_await_timeout2(_ID, To, ServerSA, NewSock) ->
    Sock = NewSock(),
    %% ?SEV_IPRINT("~w: try connect", [ID]),
    Start = t(),
    case socket:connect(Sock, ServerSA, To) of
        {error, timeout} ->
            Stop  = t(),
            TDiff = Stop - Start,
            if
                (TDiff >= To) ->
                    (catch socket:close(Sock)),
                    ok;
                true ->
                    (catch socket:close(Sock)),
                    ?FAIL({unexpected_timeout, TDiff, To})
            end;
        {error, econnreset = _Reason} ->
            (catch socket:close(Sock)),
            ok;
        {error, Reason} ->
            (catch socket:close(Sock)),
            ?FAIL({connect, Reason});
        ok ->
            {ok, Sock}
    end.

api_to_connect_tcp_await_timeout3([]) ->
    ok;
api_to_connect_tcp_await_timeout3([Sock|Socka]) ->
    (catch socket:close(Sock)),
    api_to_connect_tcp_await_timeout3(Socka).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the accept timeout option
%% on an IPv4 TCP (stream) socket.
api_to_accept_tcp4(suite) ->
    [];
api_to_accept_tcp4(doc) ->
    [];
api_to_accept_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_accept_tcp4,
           fun() ->
                   InitState = #{domain => inet, timeout => 5000},
                   ok = api_to_accept_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the accept timeout option
%% on an IPv6 TCP (stream) socket.
api_to_accept_tcp6(suite) ->
    [];
api_to_accept_tcp6(doc) ->
    [];
api_to_accept_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_accept_tcp4,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6, timeout => 5000},
                   ok = api_to_accept_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_to_accept_tcp(InitState) ->
    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create (listen) socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = _State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, _} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},

         %% *** The actual test part ***
         #{desc => "attempt to accept (without success)",
           cmd  => fun(#{lsock := LSock, timeout := To} = State) ->
                           Start = t(),
                           case socket:accept(LSock, To) of
                               {error, timeout} ->
                                   {ok, State#{start => Start, stop => t()}};
                               {ok, Sock} ->
                                   (catch socket:close(Sock)),
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate timeout time",
           cmd  => fun(#{start := Start, stop := Stop, timeout := To} = _State) ->
                           TDiff  = Stop - Start,
                           if
                               (TDiff >= To) ->
                                   ok;
                               true ->
                                   {error, {unexpected_timeout, TDiff, To}}
                           end
                   end},

         %% *** Close (listen) socket ***
         #{desc => "close (listen) socket",
           cmd  => fun(#{lsock := LSock} = State) ->
                           sock_close(LSock),
                           {ok, maps:remove(sock3, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("create tester evaluator"),
    Tester = ?SEV_START("tester", TesterSeq, InitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the multi accept timeout option
%% on an IPv4 TCP (stream) socket with multiple acceptor processes 
%% (three in this case).
api_to_maccept_tcp4(suite) ->
    [];
api_to_maccept_tcp4(doc) ->
    [];
api_to_maccept_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_to_maccept_tcp4,
           fun() ->
                   InitState = #{domain => inet, timeout => 5000},
                   ok = api_to_maccept_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the accept timeout option
%% on an IPv6 TCP (stream) socket.
api_to_maccept_tcp6(suite) ->
    [];
api_to_maccept_tcp6(doc) ->
    [];
api_to_maccept_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_to_maccept_tcp4,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6, timeout => 5000},
                   ok = api_to_maccept_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_to_maccept_tcp(InitState) ->
    PrimAcceptorSeq =
        [
         %% *** Init part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create (listen) socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, lsa := LSA} = _State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, _} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{lsock := LSock, tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, LSock),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "attempt to accept (without success)",
           cmd  => fun(#{lsock := LSock, timeout := To} = State) ->
                           Start = t(),
                           case socket:accept(LSock, To) of
                               {error, timeout} ->
                                   {ok, State#{start => Start, stop => t()}};
                               {ok, Sock} ->
                                   ?SEV_EPRINT("Unexpected accept success: "
                                               "~n   ~p", [Sock]),
                                   (catch socket:close(Sock)),
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate timeout time",
           cmd  => fun(#{start := Start, stop := Stop, timeout := To} = _State) ->
                           TDiff  = Stop - Start,
                           if
                               (TDiff >= To) ->
                                   ok;
                               true ->
                                   {error, {unexpected_timeout, TDiff, To}}
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         %% *** Terminate ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_TERMINATE(Tester, tester),
                           ok
                   end},
         %% *** Close (listen) socket ***
         #{desc => "close (listen) socket",
           cmd  => fun(#{lsock := LSock} = State) ->
                           sock_close(LSock),
                           {ok, maps:remove(lsock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    SecAcceptorSeq =
        [
         %% *** Init part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, LSock} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester,
                                       lsock  => LSock}}
                           
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% *** The actual test part ***
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "attempt to accept (without success)",
           cmd  => fun(#{lsock := LSock, timeout := To} = State) ->
                           Start = t(),
                           case socket:accept(LSock, To) of
                               {error, timeout} ->
                                   {ok, State#{start => Start, stop => t()}};
                               {ok, Sock} ->
                                   (catch socket:close(Sock)),
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate timeout time",
           cmd  => fun(#{start := Start, stop := Stop, timeout := To} = State) ->
                           TDiff  = Stop - Start,
                           if
                               (TDiff >= To) ->
                                   State1 = maps:remove(start, State),
                                   State2 = maps:remove(stop,  State1),
                                   {ok, State2};
                               true ->
                                   {error, {unexpected_timeout, TDiff, To}}
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         %% *** Terminate ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    TesterSeq =
        [
         %% Init part
         #{desc => "monitor prim-acceptor",
           cmd  => fun(#{prim_acceptor := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor sec-acceptor 1",
           cmd  => fun(#{sec_acceptor1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor sec-acceptor 2",
           cmd  => fun(#{sec_acceptor2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},


         %% Start the prim-acceptor
         #{desc => "start prim-acceptor",
           cmd  => fun(#{prim_acceptor := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await prim-acceptor ready (init)",
           cmd  => fun(#{prim_acceptor := Pid} = State) ->
                           {ok, Sock} = ?SEV_AWAIT_READY(Pid, prim_acceptor, init),
                           {ok, State#{lsock => Sock}}
                   end},

         %% Start sec-acceptor-1
         #{desc => "start sec-acceptor 1",
           cmd  => fun(#{sec_acceptor1 := Pid, lsock := LSock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, LSock),
                           ok
                   end},
         #{desc => "await sec-acceptor 1 ready (init)",
           cmd  => fun(#{sec_acceptor1 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, sec_acceptor1, init)
                   end},

         %% Start sec-acceptor-2
         #{desc => "start sec-acceptor 2",
           cmd  => fun(#{sec_acceptor2 := Pid, lsock := LSock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, LSock),
                           ok
                   end},
         #{desc => "await sec-acceptor 2 ready (init)",
           cmd  => fun(#{sec_acceptor2 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, sec_acceptor2, init)
                   end},

         %% Activate the acceptor(s)
         #{desc => "active prim-acceptor",
           cmd  => fun(#{prim_acceptor := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         #{desc => "active sec-acceptor 1",
           cmd  => fun(#{sec_acceptor1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         #{desc => "active sec-acceptor 2",
           cmd  => fun(#{sec_acceptor2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},

         %% Await acceptor(s) completions
         #{desc => "await prim-acceptor ready (accept)",
           cmd  => fun(#{prim_acceptor := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, prim_acceptor, accept)
                   end},
         #{desc => "await sec-acceptor 1 ready (accept)",
           cmd  => fun(#{sec_acceptor1 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, sec_acceptor1, accept)
                   end},
         #{desc => "await sec-acceptor 2 ready (accept)",
           cmd  => fun(#{sec_acceptor2 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, sec_acceptor2, accept)
                   end},

         %% Terminate
         #{desc => "order prim-acceptor to terminate",
           cmd  => fun(#{prim_acceptor := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await prim-acceptor termination",
           cmd  => fun(#{prim_acceptor := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(prim_acceptor, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order sec-acceptor 1 to terminate",
           cmd  => fun(#{sec_acceptor1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await sec-acceptor 1 termination",
           cmd  => fun(#{sec_acceptor1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(sec_acceptor1, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order sec-acceptor 2 to terminate",
           cmd  => fun(#{sec_acceptor2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await sec-acceptor 2 termination",
           cmd  => fun(#{sec_acceptor2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(sec_acceptor2, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         
         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("create prim-acceptor evaluator"),
    PrimAInitState = InitState,
    PrimAcceptor = ?SEV_START("prim-acceptor", PrimAcceptorSeq, PrimAInitState),

    i("create sec-acceptor 1 evaluator"),
    SecAInitState1 = maps:remove(domain, InitState),
    SecAcceptor1 = ?SEV_START("sec-acceptor-1", SecAcceptorSeq, SecAInitState1),
    
    i("create sec-acceptor 2 evaluator"),
    SecAInitState2 = SecAInitState1,
    SecAcceptor2 = ?SEV_START("sec-acceptor-2", SecAcceptorSeq, SecAInitState2),

    i("create tester evaluator"),
    TesterInitState = #{prim_acceptor => PrimAcceptor#ev.pid,
                        sec_acceptor1 => SecAcceptor1#ev.pid,
                        sec_acceptor2 => SecAcceptor2#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([PrimAcceptor, SecAcceptor1, SecAcceptor2, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the send timeout option
%% on an IPv4 TCP (stream) socket.
api_to_send_tcp4(suite) ->
    [];
api_to_send_tcp4(doc) ->
    [];
api_to_send_tcp4(_Config) when is_list(_Config) ->
    tc_try(api_to_send_tcp4,
           fun() ->
                   not_yet_implemented()%% ,
                   %% ok = api_to_send_tcp(inet)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the send timeout option
%% on an IPv6 TCP (stream) socket.
api_to_send_tcp6(suite) ->
    [];
api_to_send_tcp6(doc) ->
    [];
api_to_send_tcp6(_Config) when is_list(_Config) ->
    tc_try(api_to_send_tcp6,
           fun() ->
                   not_yet_implemented()%% ,
                   %% ok = api_to_send_tcp(inet6)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the sendto timeout option
%% on an IPv4 UDP (dgram) socket.
api_to_sendto_udp4(suite) ->
    [];
api_to_sendto_udp4(doc) ->
    [];
api_to_sendto_udp4(_Config) when is_list(_Config) ->
    tc_try(api_to_sendto_udp4,
           fun() ->
                   not_yet_implemented()%% ,
                   %% ok = api_to_sendto_to_udp(inet)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the sendto timeout option
%% on an IPv6 UDP (dgram) socket.
api_to_sendto_udp6(suite) ->
    [];
api_to_sendto_udp6(doc) ->
    [];
api_to_sendto_udp6(_Config) when is_list(_Config) ->
    tc_try(api_to_sendto_udp6,
           fun() ->
                   not_yet_implemented()%% ,
                   %% ok = api_to_sendto_to_udp(inet6)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the sendmsg timeout option
%% on an IPv4 TCP (stream) socket.
api_to_sendmsg_tcp4(suite) ->
    [];
api_to_sendmsg_tcp4(doc) ->
    [];
api_to_sendmsg_tcp4(_Config) when is_list(_Config) ->
    tc_try(api_to_sendmsg_tcp4,
           fun() ->
                   not_yet_implemented()%% ,
                   %% ok = api_to_sendmsg_tcp(inet)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the sendmsg timeout option
%% on an IPv6 TCP (stream) socket.
api_to_sendmsg_tcp6(suite) ->
    [];
api_to_sendmsg_tcp6(doc) ->
    [];
api_to_sendmsg_tcp6(_Config) when is_list(_Config) ->
    tc_try(api_to_sendmsg_tcp6,
           fun() ->
                   not_yet_implemented()%% ,
                   %% ok = api_to_sendmsg_tcp(inet6)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recv timeout option
%% on an IPv4 UDP (dgram) socket. To test this we must connect
%% the socket.
api_to_recv_udp4(suite) ->
    [];
api_to_recv_udp4(doc) ->
    [];
api_to_recv_udp4(_Config) when is_list(_Config) ->
    tc_try(api_to_recv_udp4,
           fun() ->
                   not_yet_implemented()%%,
                   %%ok = api_to_recv_udp(inet)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recv timeout option
%% on an IPv6 UDP (dgram) socket. To test this we must connect
%% the socket.
api_to_recv_udp6(suite) ->
    [];
api_to_recv_udp6(doc) ->
    [];
api_to_recv_udp6(_Config) when is_list(_Config) ->
    tc_try(api_to_recv_udp6,
           fun() ->
                   not_yet_implemented()%% ,
                   %% ok = api_to_recv_udp(inet6)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recv timeout option
%% on an IPv4 TCP (stream) socket.
api_to_recv_tcp4(suite) ->
    [];
api_to_recv_tcp4(doc) ->
    [];
api_to_recv_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recv_tcp4,
           fun() ->
                   Recv = fun(Sock, To) -> socket:recv(Sock, 0, To) end,
                   InitState = #{domain  => inet,
                                 recv    => Recv,
                                 timeout => 2000},
                   ok = api_to_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recv timeout option
%% on an IPv6 TCP (stream) socket.
api_to_recv_tcp6(suite) ->
    [];
api_to_recv_tcp6(doc) ->
    [];
api_to_recv_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recv_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   case socket:supports(ipv6) of
                       true ->
                           Recv = fun(Sock, To) -> 
                                          socket:recv(Sock, 0, To)
                                  end,
                           InitState = #{domain  => inet6,
                                         recv    => Recv,
                                         timeout => 2000},
                           ok = api_to_receive_tcp(InitState);
                       false ->
                           skip("ipv6 not supported")
                   end
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_to_receive_tcp(InitState) ->
    process_flag(trap_exit, true),

    ServerSeq = 
        [
         %% *** Wait for start order ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester}) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{lsock := LSock, local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket (with backlog = 1)",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock, 1)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (accept and recv)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept_recv)
                   end},
         #{desc => "attempt accept",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "attempt to recv (without success)",
           cmd  => fun(#{sock := Sock, recv := Recv, timeout := To} = State) ->
                           Start = t(),
                           case Recv(Sock, To) of
                               {error, timeout} ->
                                   {ok, State#{start => Start, stop => t()}};
                               {ok, _Data} ->
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate timeout time",
           cmd  => fun(#{start := Start, stop := Stop, timeout := To} = State) ->
                           TDiff  = Stop - Start,
                           if
                               (TDiff >= To) ->
                                   State1 = maps:remove(start, State),
                                   State2 = maps:remove(stop,  State1),
                                   {ok, State2};
                               true ->
                                   {error, {unexpected_timeout, TDiff, To}}
                           end
                   end},
         #{desc => "announce ready (recv timeout success)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept_recv),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close (traffic) socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           sock_close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},
         #{desc => "close (listen) socket",
           cmd  => fun(#{lsock := LSock} = State) ->
                           sock_close(LSock),
                           {ok, maps:remove(lsock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           {Tester, Port} = ?SEV_AWAIT_START(),
                           {ok, State#{tester      => Tester,
                                       server_port => Port}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain, server_port := Port} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           SSA = LSA#{port => Port},
                           {ok, State#{local_sa => LSA, server_sa => SSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% *** The actual test ***
         #{desc => "await continue (with connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect)
                   end},
         #{desc => "connect",
           cmd  => fun(#{sock := Sock, server_sa := SSA}) ->
                           sock_connect(Sock, SSA),
                           ok
                   end},

         %% *** Termination ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           sock_close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Server} = _State) ->
                           _MRef = erlang:monitor(process, Server),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Client} = _State) ->
                           _MRef = erlang:monitor(process, Client),
                           ok
                   end},

         %% *** Activate server ***
         #{desc => "start server",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_START(Server),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Server} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Server, server, init),
                           {ok, State#{server_port => Port}}
                   end},
         #{desc => "order server to continue (with accept)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, accept_recv),
                           ok
                   end},

         %% *** Activate client ***
         #{desc => "start client",
           cmd  => fun(#{client := Client, server_port := Port} = _State) ->
                           ?SEV_ANNOUNCE_START(Client, Port),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, init)
                   end},

         %% *** The actual test ***
         #{desc => "order client to continue (with connect)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, connect),
                           ok
                   end},
         #{desc => "await server ready (accept/recv)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept_recv)
                   end},

         %% *** Termination ***
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Client} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Client) of
                               ok ->
                                   State1 = maps:remove(client, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Server} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Server) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   State2 = maps:remove(server_port, State1),
                                   {ok, State2};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    
    i("start server evaluator"),
    ServerInitState = InitState,
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator"),
    ClientInitState = InitState,
    Client = ?SEV_START("client", ClientSeq, ClientInitState),

    i("start tester evaluator"),
    TesterInitState = #{server => Server#ev.pid, 
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recvfrom timeout option
%% on an IPv4 UDP (dgram) socket.
api_to_recvfrom_udp4(suite) ->
    [];
api_to_recvfrom_udp4(doc) ->
    [];
api_to_recvfrom_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recvfrom_udp4,
           fun() ->
                   Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end,
                   InitState = #{domain  => inet,
                                 recv    => Recv,
                                 timeout => 2000},
                   ok = api_to_receive_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recvfrom timeout option
%% on an IPv6 UDP (dgram) socket.
api_to_recvfrom_udp6(suite) ->
    [];
api_to_recvfrom_udp6(doc) ->
    [];
api_to_recvfrom_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recvfrom_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end,
                   InitState = #{domain  => inet6,
                                 recv    => Recv,
                                 timeout => 2000},
                   ok = api_to_receive_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

api_to_receive_udp(InitState) ->
    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, lsa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** The actual test ***
         #{desc => "attempt to read (without success)",
           cmd  => fun(#{sock := Sock, recv := Recv, timeout := To} = State) ->
                           Start = t(),
                           case Recv(Sock, To) of
                               {error, timeout} ->
                                   {ok, State#{start => Start,
                                               stop => t()}};
                               {ok, _} ->
                                   {error, unexpected_sucsess};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate timeout time",
           cmd  => fun(#{start := Start, stop := Stop, timeout := To} = _State) ->
                           TDiff  = Stop - Start,
                           if
                               (TDiff >= To) ->
                                   ok;
                               true ->
                                   {error, {unexpected_timeout, TDiff, To}}
                           end
                   end},
         
         %% *** Termination ***
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = _State) ->
                           %% socket:setopt(Sock, otp, debug, true),
                           sock_close(Sock),
                           ok
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start tester evaluator"),
    Tester = ?SEV_START("tester", TesterSeq, InitState),
    
    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recvmsg timeout option
%% on an IPv4 UDP (dgram) socket.
api_to_recvmsg_udp4(suite) ->
    [];
api_to_recvmsg_udp4(doc) ->
    [];
api_to_recvmsg_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recvmsg_udp4,
           fun() ->
                   Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
                   InitState = #{domain  => inet,
                                 recv    => Recv,
                                 timeout => 2000},
                   ok = api_to_receive_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recvmsg timeout option
%% on an IPv6 UDP (dgram) socket.
api_to_recvmsg_udp6(suite) ->
    [];
api_to_recvmsg_udp6(doc) ->
    [];
api_to_recvmsg_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recvmsg_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
                   InitState = #{domain  => inet6,
                                 recv    => Recv,
                                 timeout => 2000},
                   ok = api_to_receive_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recvmsg timeout option
%% on an IPv4 TCP (stream) socket.
api_to_recvmsg_tcp4(suite) ->
    [];
api_to_recvmsg_tcp4(doc) ->
    [];
api_to_recvmsg_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recvmsg_tcp4,
           fun() ->
                   Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
                   InitState = #{domain  => inet,
                                 recv    => Recv,
                                 timeout => 2000},
                   ok = api_to_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This test case is intended to test the recvmsg timeout option
%% on an IPv6 TCP (stream) socket.
api_to_recvmsg_tcp6(suite) ->
    [];
api_to_recvmsg_tcp6(doc) ->
    [];
api_to_recvmsg_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_to_recvmsg_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
                   InitState = #{domain  => inet6,
                                 recv    => Recv,
                                 timeout => 2000},
                   ok = api_to_receive_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                                                     %%
%%                         SOCKET CLOSURE                              %%
%%                                                                     %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sockets are cleaned up
%% ("removed") when the controlling process terminates (without explicitly 
%% calling the close function). For a IPv4 TCP (stream) socket.

sc_cpe_socket_cleanup_tcp4(suite) ->
    [];
sc_cpe_socket_cleanup_tcp4(doc) ->
    [];
sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(sc_cpe_socket_cleanup_tcp4,
           fun() ->
                   InitState = #{domain   => inet,
                                 type     => stream,
                                 protocol => tcp},
                   ok = sc_cpe_socket_cleanup(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sockets are cleaned up
%% ("removed") when the controlling process terminates (without explicitly 
%% calling the close function). For a IPv6 TCP (stream) socket.

sc_cpe_socket_cleanup_tcp6(suite) ->
    [];
sc_cpe_socket_cleanup_tcp6(doc) ->
    [];
sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(sc_cpe_socket_cleanup_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain   => inet6,
                                 type     => stream,
                                 protocol => tcp},
                   ok = sc_cpe_socket_cleanup(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sockets are cleaned up
%% ("removed") when the controlling process terminates (without explicitly 
%% calling the close function). For a Unix Domain (stream) socket (TCP).

sc_cpe_socket_cleanup_tcpL(suite) ->
    [];
sc_cpe_socket_cleanup_tcpL(doc) ->
    [];
sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(sc_cpe_socket_cleanup_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain   => local,
                                 type     => stream,
                                 protocol => default},
                   ok = sc_cpe_socket_cleanup(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sockets are cleaned up
%% ("removed") when the controlling process terminates (without explicitly 
%% calling the close function). For a IPv4 UDP (dgram) socket.

sc_cpe_socket_cleanup_udp4(suite) ->
    [];
sc_cpe_socket_cleanup_udp4(doc) ->
    [];
sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(sc_cpe_socket_cleanup_udp4,
           fun() ->
                   InitState = #{domain   => inet,
                                 type     => dgram,
                                 protocol => udp},
                   ok = sc_cpe_socket_cleanup(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sockets are cleaned up
%% (removed) when the controlling process terminates (without explicitly 
%% calling the close function). For a IPv6 UDP (dgram) socket.

sc_cpe_socket_cleanup_udp6(suite) ->
    [];
sc_cpe_socket_cleanup_udp6(doc) ->
    [];
sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(sc_cpe_socket_cleanup_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain   => inet6,
                                 type     => dgram,
                                 protocol => udp},
                   ok = sc_cpe_socket_cleanup(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sockets are cleaned up
%% ("removed") when the controlling process terminates (without explicitly 
%% calling the close function). For a Unix Domain (dgram) socket (UDP).

sc_cpe_socket_cleanup_udpL(suite) ->
    [];
sc_cpe_socket_cleanup_udpL(doc) ->
    [];
sc_cpe_socket_cleanup_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(sc_cpe_socket_cleanup_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain   => local,
                                 type     => dgram,
                                 protocol => default},
                   ok = sc_cpe_socket_cleanup(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

sc_cpe_socket_cleanup(InitState) ->
    OwnerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "create socket",
           cmd  => fun(#{domain   := Domain, 
                         type     := Type, 
                         protocol := Proto} = State) ->
                           case socket:open(Domain, Type, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Sock),
                           ok
                   end},

         %% *** The actual test ***
         %% We *intentially* leave the socket "as is", no explicit close
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor owner",
           cmd  => fun(#{owner := Owner} = _State) ->
                           _MRef = erlang:monitor(process, Owner),
                           ok
                   end},
         #{desc => "order (owner) start",
           cmd  => fun(#{owner := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await (owner) ready",
           cmd  => fun(#{owner := Pid} = State) ->
                           {ok, Sock} = ?SEV_AWAIT_READY(Pid, owner, init),
                           {ok, State#{sock => Sock}}
                   end},
         #{desc => "verify owner as controlling-process",
           cmd  => fun(#{owner := Pid, sock := Sock} = _State) ->
                           case socket:getopt(Sock, otp, controlling_process) of
                               {ok, Pid} ->
                                   ok;
                               {ok, Other} ->
                                   {error, {unexpected_owner, Other}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order (owner) terminate",
           cmd  => fun(#{owner := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await (owner) termination",
           cmd  => fun(#{owner := Pid} = _State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         %% The reason we get closed, is that as long as there is a ref to 
         %% the resource (socket), then it will not be garbage collected.
         #{desc => "verify no socket (closed)",
           cmd  => fun(#{owner := Pid, sock := Sock} = _State) ->
                           case socket:getopt(Sock, otp, controlling_process) of
                               {ok, OtherPid} ->
                                   {error, {unexpected_success, Pid, OtherPid}};
                               {error, closed} ->
                                   ok;
                               {error, Reason} ->
                                   ?SEV_IPRINT("expected failure: ~p", [Reason]),
                                   {error, {unexpected_failure, Reason}}
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start (socket) owner evaluator"),
    Owner = ?SEV_START("owner", OwnerSeq, InitState),

    i("start tester evaluator"),
    TesterInitState = #{owner => Owner#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Owner, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while a process is calling the recv function.
%% Socket is IPv4.
%% 
%% <KOLLA>
%% 
%% We should really have a similar test cases for when the controlling
%% process exits and there are other processes in recv, accept, and 
%% all the other functions.
%% 
%% </KOLLA>

sc_lc_recv_response_tcp4(suite) ->
    [];
sc_lc_recv_response_tcp4(doc) ->
    [];
sc_lc_recv_response_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_lc_recv_response_tcp4,
           fun() ->
                   Recv      = fun(Sock) -> socket:recv(Sock) end,
                   InitState = #{domain   => inet,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recv function.
%% Socket is IPv6.

sc_lc_recv_response_tcp6(suite) ->
    [];
sc_lc_recv_response_tcp6(doc) ->
    [];
sc_lc_recv_response_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_lc_recv_response_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recv(Sock) end,
                   InitState = #{domain   => inet6,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recv function.
%% Socket is Unix Domain (stream) socket.

sc_lc_recv_response_tcpL(suite) ->
    [];
sc_lc_recv_response_tcpL(doc) ->
    [];
sc_lc_recv_response_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_lc_recv_response_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recv(Sock) end,
                   InitState = #{domain   => local,
                                 protocol => default,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

sc_lc_receive_response_tcp(InitState) ->
    %% This (acceptor) is the server that accepts connections.
    %% But it is also suppose to close the connection socket, 
    %% and trigger the read failure (=closed) for the handler process.
    AcceptorSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create (listen) socket",
           cmd  => fun(#{domain   := Domain, 
                         protocol := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{domain := local,
                         lsock  := LSock,
                         lsa    := LSA} = _State) ->
                           ?SEV_IPRINT("bind to LSA: "
                                       "~n   ~p", [LSA]),
                           case socket:bind(LSock, LSA) of
                               {ok, _Port} ->
                                   ok; % We do not care about the port for local
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{lsock := LSock,
                         lsa   := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("bound to port: ~w", [Port]),
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain := local,
                         tester := Tester,
                         lsa    := #{path := Path}}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Path),
                           ok;
                      (#{tester := Tester, lport := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Port),
                           ok
                   end},
                           
         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, accept) of
                               {ok, {H1, H2, H3}} ->
                                   {ok, State#{handler1 => H1,
                                               handler2 => H2,
                                               handler3 => H3}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await accept",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("connection accepted: "
                                               "~n   ~p", [socket:sockname(Sock)]),
                                   {ok, State#{csock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},
         #{desc => "transfer connection to handler 1",
           cmd  => fun(#{handler1 := Handler, csock := Sock}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Handler, transfer, Sock),
                           ok
                   end},
         #{desc => "transfer connection to handler 2",
           cmd  => fun(#{handler2 := Handler, csock := Sock}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Handler, transfer, Sock),
                           ok
                   end},
         #{desc => "transfer connection to handler 3",
           cmd  => fun(#{handler3 := Handler, csock := Sock}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Handler, transfer, Sock),
                           ok
                   end},
         #{desc => "await continue (close)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, close),
                           ok
                   end},
         #{desc => "close connection socket",
           cmd  => fun(#{csock := Sock} = State) ->
                           case socket:close(Sock) of
                               ok ->
                                   {ok, maps:remove(csock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (close)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, close),
                           ok
                   end},

         %% *** Terminate ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{domain := local,
                         lsock  := Sock,
                         lsa    := #{path := Path}} = State) ->
                           ok = socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() ->maps:remove(lsa, State) end,
                                           fun() -> State end),
                           State2 = maps:remove(lsock, State1),
                           State3 = maps:remove(lport, State2),
                           {ok, State3};
                      (#{lsock := Sock} = State) ->
                           case socket:close(Sock) of
                               ok ->
                                   State1 = maps:remove(lsock, State),
                                   State2 = maps:remove(lport, State1),
                                   {ok, State2};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    %% The point of this is to perform the recv for which
    %% we are testing the reponse.
    HandlerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           {Tester, Acceptor} = ?SEV_AWAIT_START(),
                           {ok, State#{tester  => Tester, 
                                      acceptor => Acceptor}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},
         #{desc => "monitor acceptor",
           cmd  => fun(#{acceptor := Acceptor} = _State) ->
                           _MRef = erlang:monitor(process, Acceptor),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (transfer)",
           cmd  => fun(#{acceptor := Pid} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Pid, acceptor, transfer) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (transfer)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, transfer),
                           ok
                   end},
         #{desc => "attempt recv (=> closed)",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           %% ok = socket:setopt(Sock, otp, debug, true),
                           case Recv(Sock) of
                               {ok, _Data} ->
                                   ?SEV_EPRINT("Unexpected data received"),
                                   {error, unexpected_success};
                               {error, closed} ->
                                   ?SEV_IPRINT("received expected 'closed' "
                                               "result"),
                                   State1 = maps:remove(sock, State),
                                   {ok, State1};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected read failure: "
                                               "~n   ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv closed)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_closed),
                           ok
                   end},

         %% *** Terminate ***
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    %% The point of this is basically just to create the connection.
    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain   := Domain, 
                         protocol := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind socket to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           ?SEV_IPRINT("bind to LSA: "
                                       "~n   ~p", [LSA]),
                           case socket:bind(Sock, LSA) of
                               {ok, _} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (connect)",
           cmd  => fun(#{domain := local = Domain,
                         tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, connect) of
                               {ok, ServerPath} ->
                                   ?SEV_IPRINT("Server Path: "
                                               "~n   ~s", [ServerPath]),
                                   ServerSA = #{family => Domain,
                                                path   => ServerPath},
                                   {ok, State#{server_sa => ServerSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{tester := Tester, local_sa := LSA} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, connect) of
                               {ok, Port} ->
                                   ServerSA = LSA#{port => Port},
                                   {ok, State#{server_sa => ServerSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "connect to server",
           cmd  => fun(#{sock := Sock, server_sa := ServerSA}) ->
                           socket:connect(Sock, ServerSA)
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         %% *** Terminate ***
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end                           
                   end},
         #{desc => "close socket",
           cmd  => fun(#{domain   := local,
                         sock     := Sock,
                         local_sa := #{path := Path}} = State) ->
                           sock_close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() ->
                                                   maps:remove(local_sa, State)
                                           end,
                                           fun() -> State end),
                           {ok, maps:remove(sock, State1)};
                       (#{sock := Sock} = State) ->
                           sock_close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor acceptor",
           cmd  => fun(#{acceptor := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor handler 1",
           cmd  => fun(#{handler1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor handler 2",
           cmd  => fun(#{handler2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor handler 3",
           cmd  => fun(#{handler3 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the acceptor
         #{desc => "order acceptor start",
           cmd  => fun(#{acceptor := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await acceptor ready (init)",
           cmd  => fun(#{acceptor := Pid} = State) ->
                           case ?SEV_AWAIT_READY(Pid, acceptor, init) of
                               {ok, PortOrPath} ->
                                   {ok, State#{server_info => PortOrPath}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% Start the handler(s)
         #{desc => "order handler 1 start",
           cmd  => fun(#{acceptor := Acceptor, handler1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Acceptor),
                           ok
                   end},
         #{desc => "await handler 1 ready (init)",
           cmd  => fun(#{handler1 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, handler1, init)
                   end},
         #{desc => "order handler 2 start",
           cmd  => fun(#{acceptor := Acceptor, handler2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Acceptor),
                           ok
                   end},
         #{desc => "await handler 2 ready (init)",
           cmd  => fun(#{handler2 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, handler2, init)
                   end},
         #{desc => "order handler 3 start",
           cmd  => fun(#{acceptor := Acceptor, handler3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Acceptor),
                           ok
                   end},
         #{desc => "await handler 3 ready (init)",
           cmd  => fun(#{handler3 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, handler3, init)
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, client, init)
                   end},

         %% The actual test
         #{desc => "order acceptor to continue (accept)",
           cmd  => fun(#{acceptor := Pid, 
                         handler1 := H1, 
                         handler2 := H2, 
                         handler3 := H3} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept, {H1, H2, H3}),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client to continue (connect)",
           cmd  => fun(#{client := Pid, server_info := Info} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect, Info),
                           ok
                   end},
         #{desc => "await acceptor ready (accept)",
           cmd  => fun(#{acceptor := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, acceptor, accept)
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, connect)
                   end},
         #{desc => "await handler 1 ready (transfer)",
           cmd  => fun(#{handler1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, handler1, transfer)
                   end},
         #{desc => "await handler 2 ready (transfer)",
           cmd  => fun(#{handler2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, handler2, transfer)
                   end},
         #{desc => "await handler 3 ready (transfer)",
           cmd  => fun(#{handler3 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, handler3, transfer)
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order acceptor to continue (close connection socket)",
           cmd  => fun(#{acceptor := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await acceptor ready (close)",
           cmd  => fun(#{acceptor := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, acceptor, close)
                   end},
         #{desc => "await handler 1 ready (recv closed)",
           cmd  => fun(#{handler1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, handler1, recv_closed)
                   end},
         #{desc => "await handler 2 ready (recv closed)",
           cmd  => fun(#{handler2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, handler2, recv_closed)
                   end},
         #{desc => "await handler 3 ready (recv closed)",
           cmd  => fun(#{handler3 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, handler3, recv_closed)
                   end},

         %% Terminations
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(client, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order handler 1 to terminate",
           cmd  => fun(#{handler1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await handler 1 termination",
           cmd  => fun(#{handler1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(handler1, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order handler 2 to terminate",
           cmd  => fun(#{handler2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await handler 2 termination",
           cmd  => fun(#{handler2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(handler2, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order handler 3 to terminate",
           cmd  => fun(#{handler3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await handler 3 termination",
           cmd  => fun(#{handler3 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(handler3, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order acceptor to terminate",
           cmd  => fun(#{acceptor := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await acceptor termination",
           cmd  => fun(#{acceptor := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(acceptor, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start acceptor evaluator"),
    AccInitState = InitState,
    Acceptor = ?SEV_START("acceptor", AcceptorSeq, AccInitState),

    i("start handler 1 evaluator"),
    HandlerInitState = #{recv => maps:get(recv, InitState)},
    Handler1 = ?SEV_START("handler-1", HandlerSeq, HandlerInitState),

    i("start handler 2 evaluator"),
    Handler2 = ?SEV_START("handler-2", HandlerSeq, HandlerInitState),

    i("start handler 3 evaluator"),
    Handler3 = ?SEV_START("handler-3", HandlerSeq, HandlerInitState),

    i("start client evaluator"),
    ClientInitState = InitState,
    Client = ?SEV_START("client", ClientSeq, ClientInitState),

    i("start tester evaluator"),
    TesterInitState = #{acceptor => Acceptor#ev.pid,
                        handler1 => Handler1#ev.pid,
                        handler2 => Handler2#ev.pid,
                        handler3 => Handler3#ev.pid,
                        client   => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Acceptor, 
                            Handler1, Handler2, Handler3, 
                            Client, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while a process is calling the recvfrom function.
%% Socket is IPv4.
%% 

sc_lc_recvfrom_response_udp4(suite) ->
    [];
sc_lc_recvfrom_response_udp4(doc) ->
    [];
sc_lc_recvfrom_response_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_lc_recvfrom_response_udp4,
           fun() ->
                   Recv      = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end,
                   InitState = #{domain   => inet,
                                 protocol => udp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recv function.
%% Socket is IPv6.

sc_lc_recvfrom_response_udp6(suite) ->
    [];
sc_lc_recvfrom_response_udp6(doc) ->
    [];
sc_lc_recvfrom_response_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_lc_recvfrom_response_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv      = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end,
                   InitState = #{domain   => inet6,
                                 protocol => udp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recv function.
%% Socket is Unix Domainm (dgram) socket.

sc_lc_recvfrom_response_udpL(suite) ->
    [];
sc_lc_recvfrom_response_udpL(doc) ->
    [];
sc_lc_recvfrom_response_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_lc_recvfrom_response_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Recv      = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end,
                   InitState = #{domain   => local,
                                 protocol => default,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

sc_lc_receive_response_udp(InitState) ->
    PrimServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "open socket",
           cmd  => fun(#{domain := Domain, protocol := Proto} = State) ->
                           Sock = sock_open(Domain, dgram, Proto),
                           SA   = sock_sockname(Sock),
                           {ok, State#{sock => Sock, sa => SA}}
                   end},
         #{desc => "bind socket",
           cmd  => fun(#{sock := Sock, local_sa := LSA}) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ?SEV_IPRINT("src bound"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("src bind failed: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, sock := Sock}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Sock),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv, with timeout)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, recv) of
                               {ok, Timeout} ->
                                   {ok, State#{timeout => Timeout}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "receive, with timeout",
           cmd  => fun(#{sock := Sock, recv := Recv, timeout := Timeout}) ->
                           case Recv(Sock, Timeout) of
                               {error, timeout} ->
                                   ok;
                               {ok, _} ->
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv, with timeout)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv),
                           ok
                   end},
         #{desc => "await continue (close)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ok = ?SEV_AWAIT_CONTINUE(Tester, tester, close)
                   end},
         #{desc => "close socket",
           cmd  => fun(#{domain   := local,
                         sock     := Sock,
                         local_sa := #{path := Path}} = State) ->
                           ok = socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() ->
                                                   maps:remove(local_sa, State)
                                           end,
                                           fun() -> State end),
                           {ok, maps:remove(sock, State1)};
                      (#{sock := Sock} = State) ->
                           case socket:close(Sock) of
                               ok ->
                                   {ok, maps:remove(sock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (close)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, close),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, terminate) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    SecServerSeq =
        [
         %% *** Init part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, Sock} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, sock => Sock}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ok = ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                           
                   end},
         #{desc => "receive",
           cmd  => fun(#{sock := Sock, recv := Recv} = State) ->
                           case Recv(Sock, infinity) of
                               {error, closed} ->
                                   {ok, maps:remove(sock, State)};
                               {ok, _} ->
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv closed)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_closed),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor primary server",
           cmd  => fun(#{prim_server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor secondary server 1",
           cmd  => fun(#{sec_server1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor secondary server 2",
           cmd  => fun(#{sec_server2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor secondary server 3",
           cmd  => fun(#{sec_server3 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the primary server
         #{desc => "order 'primary server' start",
           cmd  => fun(#{prim_server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await 'primary server' ready (init)",
           cmd  => fun(#{prim_server := Pid} = State) ->
                           {ok, Sock} = ?SEV_AWAIT_READY(Pid, prim_server, init),
                           {ok, State#{sock => Sock}}
                   end},

         %% Start the secondary server 1
         #{desc => "order 'secondary server 1' start",
           cmd  => fun(#{sec_server1 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await 'secondary server 1' ready (init)",
           cmd  => fun(#{sec_server1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_server1, init)
                   end},

         %% Start the secondary server 2
         #{desc => "order 'secondary server 2' start",
           cmd  => fun(#{sec_server2 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await 'secondary server 2' ready (init)",
           cmd  => fun(#{sec_server2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_server2, init)
                   end},

         %% Start the secondary server 3
         #{desc => "order 'secondary server 3' start",
           cmd  => fun(#{sec_server3 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await 'secondary server 3' ready (init)",
           cmd  => fun(#{sec_server3 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_server3, init)
                   end},


         %% The actual test
         %% Make all the seondary servers continue, with an infinit recvfrom
         %% and then the prim-server with a timed recvfrom.
         %% After the prim server notifies us (about the timeout) we order it
         %% to close the socket, which should cause the all the secondary 
         %% server to return with error-closed.

         #{desc => "order 'secondary server 1' to continue (recv)",
           cmd  => fun(#{sec_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order 'secondary server 2' to continue (recv)",
           cmd  => fun(#{sec_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order 'secondary server 3' to continue (recv)",
           cmd  => fun(#{sec_server3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order 'primary server' to continue (recv, with timeout)",
           cmd  => fun(#{prim_server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv, ?SECS(5)),
                           ok
                   end},
         #{desc => "await 'primary server' ready (recv, with timeout)",
           cmd  => fun(#{prim_server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, prim_server, recv)
                   end},
         #{desc => "order 'primary server' to continue (close)",
           cmd  => fun(#{prim_server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await 'primary server' ready (close)",
           cmd  => fun(#{prim_server := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, prim_server, close)
                   end},
         #{desc => "await 'secondary server 1' ready (closed)",
           cmd  => fun(#{sec_server1 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, sec_server1, recv_closed)
                   end},
         #{desc => "await 'secondary server 2' ready (closed)",
           cmd  => fun(#{sec_server2 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, sec_server2, recv_closed)
                   end},
         #{desc => "await 'secondary server 3' ready (closed)",
           cmd  => fun(#{sec_server3 := Pid} = _State) ->
                           ?SEV_AWAIT_READY(Pid, sec_server3, recv_closed)
                   end},

         %% Terminations
         #{desc => "order 'secondary server 3' to terminate",
           cmd  => fun(#{sec_server3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'secondary server 3' termination",
           cmd  => fun(#{sec_server3 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(sec_server3, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order 'secondary server 2' to terminate",
           cmd  => fun(#{sec_server2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'secondary server 2' termination",
           cmd  => fun(#{sec_server2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(sec_server2, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order 'secondary server 1' to terminate",
           cmd  => fun(#{sec_server1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'secondary server 1' termination",
           cmd  => fun(#{sec_server1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(sec_server1, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order 'primary server' to terminate",
           cmd  => fun(#{prim_server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'primary server' termination",
           cmd  => fun(#{prim_server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(prim_server, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],
    

    i("start 'primary server' evaluator"),
    PrimSrvInitState = InitState,
    PrimServer = ?SEV_START("prim-server", PrimServerSeq, PrimSrvInitState),

    i("start 'secondary server 1' evaluator"),
    SecSrvInitState = #{recv => maps:get(recv, InitState)},
    SecServer1 = ?SEV_START("sec-server-1", SecServerSeq, SecSrvInitState),

    i("start 'secondary server 2' evaluator"),
    SecServer2 = ?SEV_START("sec-server-2", SecServerSeq, SecSrvInitState),

    i("start 'secondary server 3' evaluator"),
    SecServer3 = ?SEV_START("sec-server-3", SecServerSeq, SecSrvInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{prim_server => PrimServer#ev.pid,
                        sec_server1 => SecServer1#ev.pid,
                        sec_server2 => SecServer2#ev.pid,
                        sec_server3 => SecServer3#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([PrimServer, 
                            SecServer1, SecServer2, SecServer3,
                            Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv4.

sc_lc_recvmsg_response_tcp4(suite) ->
    [];
sc_lc_recvmsg_response_tcp4(doc) ->
    [];
sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_lc_recvmsg_response_tcp4,
           fun() ->
                   Recv      = fun(Sock) -> socket:recvmsg(Sock) end,
                   InitState = #{domain   => inet,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv6.

sc_lc_recvmsg_response_tcp6(suite) ->
    [];
sc_lc_recvmsg_response_tcp6(doc) ->
    [];
sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_recvmsg_response_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recvmsg(Sock) end,
                   InitState = #{domain   => inet6,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recvmsg function.
%% Socket is Unix Domain (stream) socket.

sc_lc_recvmsg_response_tcpL(suite) ->
    [];
sc_lc_recvmsg_response_tcpL(doc) ->
    [];
sc_lc_recvmsg_response_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_recvmsg_response_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recvmsg(Sock) end,
                   InitState = #{domain   => local,
                                 protocol => default,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv4.

sc_lc_recvmsg_response_udp4(suite) ->
    [];
sc_lc_recvmsg_response_udp4(doc) ->
    [];
sc_lc_recvmsg_response_udp4(_Config) when is_list(_Config) ->
    tc_try(sc_lc_recvmsg_response_udp4,
           fun() ->
                   ?TT(?SECS(10)),
                   Recv      = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
                   InitState = #{domain   => inet,
                                 protocol => udp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv6.

sc_lc_recvmsg_response_udp6(suite) ->
    [];
sc_lc_recvmsg_response_udp6(doc) ->
    [];
sc_lc_recvmsg_response_udp6(_Config) when is_list(_Config) ->
    tc_try(sc_recvmsg_response_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(10)),
                   Recv      = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
                   InitState = #{domain   => inet6,
                                 protocol => udp,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the recvmsg function.
%% Socket is Unix Domain (dgram) socket.

sc_lc_recvmsg_response_udpL(suite) ->
    [];
sc_lc_recvmsg_response_udpL(doc) ->
    [];
sc_lc_recvmsg_response_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_recvmsg_response_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Recv      = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
                   InitState = #{domain   => local,
                                 protocol => default,
                                 recv     => Recv},
                   ok = sc_lc_receive_response_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the accept function.
%% We test what happens with a non-controlling_process also, since we 
%% git the setup anyway.
%% Socket is IPv4.

sc_lc_acceptor_response_tcp4(suite) ->
    [];
sc_lc_acceptor_response_tcp4(doc) ->
    [];
sc_lc_acceptor_response_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_lc_acceptor_response_tcp4,
           fun() ->
                   InitState = #{domain   => inet,
                                 protocol => tcp},
                   ok = sc_lc_acceptor_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the accept function.
%% We test what happens with a non-controlling_process also, since we 
%% git the setup anyway.
%% Socket is IPv6.

sc_lc_acceptor_response_tcp6(suite) ->
    [];
sc_lc_acceptor_response_tcp6(doc) ->
    [];
sc_lc_acceptor_response_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_lc_acceptor_response_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain   => inet6,
                                 protocol => tcp},
                   ok = sc_lc_acceptor_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% locally closed while the process is calling the accept function.
%% We test what happens with a non-controlling_process also, since we 
%% git the setup anyway.
%% Socket is Unix Domain (stream) socket.

sc_lc_acceptor_response_tcpL(suite) ->
    [];
sc_lc_acceptor_response_tcpL(doc) ->
    [];
sc_lc_acceptor_response_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_lc_acceptor_response_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain   => local,
                                 protocol => default},
                   ok = sc_lc_acceptor_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

sc_lc_acceptor_response_tcp(InitState) ->
    PrimAcceptorSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start (from tester)",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{lsa => LSA}}
                   end},
         #{desc => "create (listen) socket",
           cmd  => fun(#{domain   := Domain, 
                         protocol := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{sock := Sock, lsa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{sock := Sock}) ->
                           socket:listen(Sock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Sock),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, accept) of
                               {ok, Timeout} ->
                                   {ok, State#{timeout => Timeout}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await connection",
           cmd  => fun(#{sock := LSock, timeout := Timeout} = _State) ->
                           case socket:accept(LSock, Timeout) of
                               {error, timeout} ->
                                   ok;
                               {ok, Sock} ->
                                   ?SEV_EPRINT("unexpected success"),
                                   (catch socket:close(Sock)),
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept timeout)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept_timeout),
                           ok
                   end},
         #{desc => "await continue (close)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ok = ?SEV_AWAIT_CONTINUE(Tester, tester, close)
                   end},
         #{desc => "close socket",
           cmd  => fun(#{domain := local,
                         sock   := Sock,
                         lsa    := #{path := Path}} = State) ->
                           case socket:close(Sock) of
                               ok ->
                                   State1 =
                                       unlink_path(Path,
                                                   fun() ->
                                                           maps:remove(lsa, State)
                                                   end,
                                                   fun() ->
                                                           State
                                                   end),
                                   {ok, maps:remove(sock, State1)};
                               {error, _} = ERROR ->
                                   unlink_path(Path),
                                   ERROR
                           end;
                      (#{sock := Sock} = State) ->
                           case socket:close(Sock) of
                               ok ->
                                   {ok, maps:remove(sock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (close)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, close),
                           ok
                   end},

                                                % Termination
         #{desc => "await terminate",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    SecAcceptorSeq =
        [
         %% *** Init part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, Sock} = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester, sock => Sock}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init)
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ok = ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "accept",
           cmd  => fun(#{sock := Sock} = State) ->
                           case socket:accept(Sock) of
                               {error, closed} ->
                                   {ok, maps:remove(sock, State)};
                               {ok, _} ->
                                   {error, unexpected_success};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept closed)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept_closed)
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor 'primary acceptor'",
           cmd  => fun(#{prim_acc := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor 'secondary acceptor 1'",
           cmd  => fun(#{sec_acc1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor secondary acceptor 2",
           cmd  => fun(#{sec_acc2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor secondary acceptor 3",
           cmd  => fun(#{sec_acc3 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the primary server
         #{desc => "order 'primary acceptor' start",
           cmd  => fun(#{prim_acc := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await 'primary acceptor' ready (init)",
           cmd  => fun(#{prim_acc := Pid} = State) ->
                           {ok, Sock} = ?SEV_AWAIT_READY(Pid, prim_acc, init),
                           {ok, State#{sock => Sock}}
                   end},

         %% Start the secondary acceptor 1
         #{desc => "order 'secondary acceptor 1' start",
           cmd  => fun(#{sec_acc1 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await 'secondary acceptor 1' ready (init)",
           cmd  => fun(#{sec_acc1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_acc1, init)
                   end},

         %% Start the secondary acceptor 2
         #{desc => "order 'secondary acceptor 2' start",
           cmd  => fun(#{sec_acc2 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await 'secondary acceptor 2' ready (init)",
           cmd  => fun(#{sec_acc2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_acc2, init)
                   end},

         %% Start the secondary acceptor 3
         #{desc => "order 'secondary acceptor 3' start",
           cmd  => fun(#{sec_acc3 := Pid, sock := Sock} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Sock),
                           ok
                   end},
         #{desc => "await 'secondary acceptor 3' ready (init)",
           cmd  => fun(#{sec_acc3 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_acc3, init)
                   end},


         %% The actual test
         %% Make all the seondary servers continue, with an infinit recvfrom
         %% and then the prim-server with a timed recvfrom.
         %% After the prim server notifies us (about the timeout) we order it
         %% to close the socket, which should cause the all the secondary 
         %% server to return with error-closed.

         #{desc => "order 'secondary acceptor 1' to continue (accept)",
           cmd  => fun(#{sec_acc1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order 'secondary acceptor 2' to continue (accept)",
           cmd  => fun(#{sec_acc2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order 'secondary acceptor 3' to continue (accept)",
           cmd  => fun(#{sec_acc3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order 'primary acceptor' to continue",
           cmd  => fun(#{prim_acc := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept, ?SECS(5)),
                           ok
                   end},
         #{desc => "await 'primary acceptor' ready (accept timeout)",
           cmd  => fun(#{prim_acc := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, prim_acc, accept_timeout)
                   end},
         #{desc => "order 'primary acceptor' to continue (close)",
           cmd  => fun(#{prim_acc := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await 'primary acceptor' ready (close)",
           cmd  => fun(#{prim_acc := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, prim_acc, close)
                   end},
         #{desc => "await 'secondary acceptor 1' ready (accept closed)",
           cmd  => fun(#{sec_acc1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_acc1, accept_closed)
                   end},
         #{desc => "await 'secondary acceptor 2' ready (accept closed)",
           cmd  => fun(#{sec_acc2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_acc2, accept_closed)
                   end},
         #{desc => "await 'secondary acceptor 3' ready (accept closed)",
           cmd  => fun(#{sec_acc3 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, sec_acc3, accept_closed)
                   end},


         %% Terminations
         #{desc => "order 'secondary acceptor 3' to terminate",
           cmd  => fun(#{sec_acc3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'secondary acceptor 3' termination",
           cmd  => fun(#{sec_acc3 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(sec_acc3, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order 'secondary acceptor 2' to terminate",
           cmd  => fun(#{sec_acc2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'secondary acceptor 2' termination",
           cmd  => fun(#{sec_acc2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(sec_acc2, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order 'secondary acceptor 1' to terminate",
           cmd  => fun(#{sec_acc1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'secondary acceptor 1' termination",
           cmd  => fun(#{sec_acc1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(sec_acc1, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order 'primary acceptor' to terminate",
           cmd  => fun(#{prim_acc := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await 'primary acceptor' termination",
           cmd  => fun(#{prim_acc := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   {ok, maps:remove(prim_acc, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    i("start 'primary acceptor' evaluator"),
    PrimAccInitState = InitState,
    PrimAcc = ?SEV_START("prim-acceptor", PrimAcceptorSeq, PrimAccInitState),

    i("start 'secondary acceptor 1' evaluator"),
    SecAccInitState = #{},
    SecAcc1 = ?SEV_START("sec-acceptor-1", SecAcceptorSeq, SecAccInitState),

    i("start 'secondary acceptor 2' evaluator"),
    SecAcc2 = ?SEV_START("sec-acceptor-2", SecAcceptorSeq, SecAccInitState),

    i("start 'secondary acceptor 3' evaluator"),
    SecAcc3 = ?SEV_START("sec-acceptor-3", SecAcceptorSeq, SecAccInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{prim_acc => PrimAcc#ev.pid,
                        sec_acc1 => SecAcc1#ev.pid,
                        sec_acc2 => SecAcc2#ev.pid,
                        sec_acc3 => SecAcc3#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([PrimAcc, SecAcc1, SecAcc2, SecAcc3, Tester]).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% remotely closed while the process is calling the recv function.
%% Socket is IPv4.
%%
%% To minimize the chance of "weirdness", we should really have test cases
%% where the two sides of the connection is on different machines. But for
%% now, we will make do with different VMs on the same host.
%%

sc_rc_recv_response_tcp4(suite) ->
    [];
sc_rc_recv_response_tcp4(doc) ->
    [];
sc_rc_recv_response_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_rc_recv_response_tcp4,
           fun() ->
                   Recv      = fun(Sock) -> socket:recv(Sock) end,
                   InitState = #{domain   => inet,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_rc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% remotely closed while the process is calling the recv function.
%% Socket is IPv6.

sc_rc_recv_response_tcp6(suite) ->
    [];
sc_rc_recv_response_tcp6(doc) ->
    [];
sc_rc_recv_response_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_rc_recv_response_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recv(Sock) end,
                   InitState = #{domain   => inet6,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_rc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% remotely closed while the process is calling the recv function.
%% Socket is Unix Domain (stream) socket.

sc_rc_recv_response_tcpL(suite) ->
    [];
sc_rc_recv_response_tcpL(doc) ->
    [];
sc_rc_recv_response_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_rc_recv_response_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recv(Sock) end,
                   InitState = #{domain   => local,
                                 protocol => default,
                                 recv     => Recv},
                   ok = sc_rc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

sc_rc_receive_response_tcp(InitState) ->
    %% Each connection are handled by handler processes.
    %% These are created (on the fly) and handled internally 
    %% by the server!
    ServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain, protocol := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{domain := local,
                         lsock  := LSock,
                         lsa    := LSA} = _State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, _Port} ->
                                   ok; % We do not care about the port for local
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{lsock    := LSock,
                         local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain   := local,
                         tester   := Tester,
                         local_sa := LSA}) ->
                           %% Actually we only need to send the path,
                           %% but to keep it simple, we send the "same"
                           %% as for non-local.
                           ?SEV_ANNOUNCE_READY(Tester, init, LSA),
                           ok;
                      (#{tester := Tester, local_sa := LSA, lport := Port}) ->
                           ServerSA = LSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept all three connections)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "accept 1",
           cmd  => fun(#{lsock := LSock, recv := Recv} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("accepted: try start handler"),
                                   Handler = sc_rc_tcp_handler_start(1, Recv, Sock),
                                   ?SEV_IPRINT("handler started"),
                                   {ok, State#{csock1   => Sock,
                                               handler1 => Handler}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await handler 1 ready (init)",
           cmd  => fun(#{tester   := Tester, 
                         handler1 := Handler1} = _State) ->
                           ?SEV_AWAIT_READY(Handler1, handler1, init, 
                                            [{tester, Tester}])
                   end},
         #{desc => "accept 2",
           cmd  => fun(#{lsock := LSock, recv := Recv} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("accepted: try start handler"),
                                   Handler = sc_rc_tcp_handler_start(2, Recv, Sock),
                                   ?SEV_IPRINT("handler started"),
                                   {ok, State#{csock2   => Sock,
                                               handler2 => Handler}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await handler 2 ready (init)",
           cmd  => fun(#{tester   := Tester, 
                         handler1 := Handler1, 
                         handler2 := Handler2} = _State) ->
                           ?SEV_AWAIT_READY(Handler2, handler2, init, 
                                            [{tester,   Tester},
                                             {handler1, Handler1}])
                   end},
         #{desc => "accept 3",
           cmd  => fun(#{lsock := LSock, recv := Recv} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("accepted: try start handler"),
                                   Handler = sc_rc_tcp_handler_start(3, Recv, Sock),
                                   ?SEV_IPRINT("handler started"),
                                   {ok, State#{csock3   => Sock,
                                               handler3 => Handler}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await handler 3 ready (init)",
           cmd  => fun(#{tester   := Tester, 
                         handler1 := Handler1, 
                         handler2 := Handler2, 
                         handler3 := Handler3} = _State) ->
                           ?SEV_AWAIT_READY(Handler3, handler3, init, 
                                            [{tester,   Tester},
                                             {handler1, Handler1},
                                             {handler2, Handler2}])
                   end},
         #{desc => "announce ready (accept all three connections)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "order handler 1 to receive",
           cmd  => fun(#{handler1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "order handler 2 to receive",
           cmd  => fun(#{handler2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "order handler 3 to receive",
           cmd  => fun(#{handler3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await ready from handler 1 (recv)",
           cmd  => fun(#{tester := Tester, handler1 := Pid} = _State) ->
                           case ?SEV_AWAIT_READY(Pid, handler1, recv, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await ready from handler 2 (recv)",
           cmd  => fun(#{tester := Tester, handler2 := Pid} = _State) ->
                           case ?SEV_AWAIT_READY(Pid, handler2, recv, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await ready from handler 3 (recv)",
           cmd  => fun(#{tester := Tester, handler3 := Pid} = _State) ->
                           case ?SEV_AWAIT_READY(Pid, handler3, recv, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv closed from all handlers)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_closed),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order handler 1 to terminate",
           cmd  => fun(#{handler1 := Pid} = _State) ->
                           %% Pid ! {terminate, self(), ok},
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await handler 1 termination",
           cmd  => fun(#{handler1 := Pid} = State) ->
                           ?SEV_AWAIT_TERMINATION(Pid),
                           State1 = maps:remove(csock1,   State),
                           State2 = maps:remove(handler1, State1),
                           {ok, State2}
                   end},
         #{desc => "order handler 2 to terminate",
           cmd  => fun(#{handler2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await handler 2 termination",
           cmd  => fun(#{handler2 := Pid} = State) ->
                           ?SEV_AWAIT_TERMINATION(Pid),
                           State1 = maps:remove(csock2,   State),
                           State2 = maps:remove(handler2, State1),
                           {ok, State2}
                   end},
         #{desc => "order handler 3 to terminate",
           cmd  => fun(#{handler3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await handler 3 termination",
           cmd  => fun(#{handler3 := Pid} = State) ->
                           ?SEV_AWAIT_TERMINATION(Pid),
                           State1 = maps:remove(csock3,   State),
                           State2 = maps:remove(handler3, State1),
                           {ok, State2}
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{domain := local,
                         lsock  := LSock,
                         lsa    := #{path := Path}} = State) ->
                           case socket:close(LSock) of
                               ok ->
                                   State1 =
                                       unlink_path(Path,
                                                   fun() ->
                                                           maps:remove(lsa, State)
                                                   end,
                                                   fun() ->
                                                           State
                                                   end),
                                   {ok, maps:remove(lsock, State1)};
                               {error, _} = ERROR ->
                                   unlink_path(Path),
                                   ERROR
                           end;
                      (#{lsock := LSock} = State) ->
                           case socket:close(LSock) of
                               ok ->
                                   {ok, maps:remove(lsock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, {NodeID, ServerSA}} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester, 
                                       node_id   => NodeID, 
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "create node",
           cmd  => fun(#{host := Host, node_id := NodeID} = State) ->
                           case start_node(Host, l2a(f("client_~w", [NodeID]))) of
                               {ok, Node} ->
                                   ?SEV_IPRINT("client node ~p started", [Node]),
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor client node 1",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "start remote client on client node",
           cmd  => fun(#{node := Node} = State) ->
                           Pid = sc_rc_tcp_client_start(Node),
                           ?SEV_IPRINT("client ~p started", [Pid]),
                           {ok, State#{rclient => Pid}}
                   end},
         #{desc => "monitor remote client",
           cmd  => fun(#{rclient := Pid}) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "order remote client to start",
           cmd  => fun(#{rclient   := Client,
                         server_sa := ServerSA,
                         protocol  := Proto}) ->
                           ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}),
                           ok
                   end},
         #{desc => "await remote client ready",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, init, 
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect, 
                                               [{rclient, Client}]),
                           ok
                   end},
         #{desc => "order remote client to continue (connect)",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, connect),
                           ok
                   end},
         #{desc => "await client process ready (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, connect, 
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (connected)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},
         #{desc => "await continue (close)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, close, 
                                               [{rclient, Client}]),
                           ok
                   end},
         #{desc => "order remote client to close",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, close),
                           ok
                   end},
         #{desc => "await remote client ready (closed)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, close, 
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (close)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, close),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester  := Tester, 
                         rclient := Client} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester,
                                                     [{rclient, Client}]) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "kill remote client",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await remote client termination",
           cmd  => fun(#{rclient := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(rclient, State),
                           {ok, State1}
                   end},
         #{desc => "stop client node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await client node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   State1 = maps:remove(node_id, State),
                                   State2 = maps:remove(node,    State1),
                                   {ok, State2}
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client 1",
           cmd  => fun(#{client1 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client 2",
           cmd  => fun(#{client2 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client 3",
           cmd  => fun(#{client3 := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},

         %% Start the client(s)
         #{desc => "order client 1 start",
           cmd  => fun(#{client1   := Pid, 
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, {1, ServerSA}),
                           ok
                   end},
         #{desc => "await client 1 ready (init)",
           cmd  => fun(#{client1 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client1, init)
                   end},
         #{desc => "order client 2 start",
           cmd  => fun(#{client2   := Pid, 
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, {2, ServerSA}),
                           ok
                   end},
         #{desc => "await client 2 ready (init)",
           cmd  => fun(#{client2 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client2, init)
                   end},
         #{desc => "order client 3 start",
           cmd  => fun(#{client3   := Pid, 
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, {3, ServerSA}),
                           ok
                   end},
         #{desc => "await client 3 ready (init)",
           cmd  => fun(#{client3 := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client3, init)
                   end},

         %% The actual test
         #{desc => "order server continue (accept)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client 1 continue (connect)",
           cmd  => fun(#{client1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await client 1 ready (connect)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Client1, client1, connect, 
                                            [{server,  Server},
                                             {client2, Client2},
                                             {client3, Client3}]),
                           ok
                   end},
         #{desc => "order client 2 continue (connect)",
           cmd  => fun(#{client2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await client 2 ready (connect)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Client2, client2, connect, 
                                            [{server,  Server},
                                             {client1, Client1},
                                             {client3, Client3}]),
                           ok
                   end},
         #{desc => "order client 3 continue (connect)",
           cmd  => fun(#{client3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await client 3 ready (connect)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Client3, client3, connect, 
                                            [{server,  Server},
                                             {client1, Client1},
                                             {client2, Client2}]),
                           ok
                   end},
         #{desc => "await server ready (accept from all connections)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept,
                                            [{client1, Client1},
                                             {client2, Client2},
                                             {client3, Client3}]),
                           ok
                   end},
         #{desc => "order server continue (recv for all connections)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client 1 continue (close)",
           cmd  => fun(#{client1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await client 1 ready (close)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Client1, client1, close, 
                                            [{server,  Server},
                                             {client2, Client2},
                                             {client3, Client3}]),
                           ok
                   end},
         #{desc => "order client 2 continue (close)",
           cmd  => fun(#{client2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await client 2 ready (close)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Client2, client2, close, 
                                            [{server,  Server},
                                             {client1, Client1},
                                             {client3, Client3}]),
                           ok
                   end},
         #{desc => "order client 3 continue (close)",
           cmd  => fun(#{client3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await client 3 ready (close)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Client3, client1, close, 
                                            [{server,  Server},
                                             {client1, Client1},
                                             {client2, Client2}]),
                           ok
                   end},
         #{desc => "await server ready (close for all connections)",
           cmd  => fun(#{server  := Server,
                         client1 := Client1,
                         client2 := Client2,
                         client3 := Client3} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, recv_closed,
                                            [{client1, Client1},
                                             {client2, Client2},
                                             {client3, Client3}]),
                           ok
                   end},

         %% Terminations
         #{desc => "order client 1 to terminate",
           cmd  => fun(#{client1 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client 1 termination",
           cmd  => fun(#{client1 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client1, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order client 2 to terminate",
           cmd  => fun(#{client2 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client 2 termination",
           cmd  => fun(#{client2 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client2, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order client 3 to terminate",
           cmd  => fun(#{client3 := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client 3 termination",
           cmd  => fun(#{client3 := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client3, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    ServerInitState = InitState,
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator(s)"),
    ClientInitState = InitState#{host => local_host()},
    Client1 = ?SEV_START("client-1", ClientSeq, ClientInitState),
    Client2 = ?SEV_START("client-2", ClientSeq, ClientInitState),
    Client3 = ?SEV_START("client-3", ClientSeq, ClientInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server  => Server#ev.pid,
                        client1 => Client1#ev.pid,
                        client2 => Client2#ev.pid,
                        client3 => Client3#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Server,
                            Client1, Client2, Client3,
                            Tester]).


sc_rc_tcp_client_start(Node) ->
    Self = self(),
    Fun  = fun() -> sc_rc_tcp_client(Self) end,
    erlang:spawn(Node, Fun).


sc_rc_tcp_client(Parent) ->
    sc_rc_tcp_client_init(Parent),
    {ServerSA, Proto} = sc_rc_tcp_client_await_start(Parent),
    Domain   = maps:get(family, ServerSA),
    Sock     = sc_rc_tcp_client_create(Domain, Proto),
    Path     = sc_rc_tcp_client_bind(Sock, Domain),
    sc_rc_tcp_client_announce_ready(Parent, init),
    sc_rc_tcp_client_await_continue(Parent, connect),
    sc_rc_tcp_client_connect(Sock, ServerSA),
    sc_rc_tcp_client_announce_ready(Parent, connect),
    sc_rc_tcp_client_await_continue(Parent, close),
    sc_rc_tcp_client_close(Sock, Path),
    sc_rc_tcp_client_announce_ready(Parent, close),
    Reason = sc_rc_tcp_client_await_terminate(Parent),
    ?SEV_IPRINT("terminate"),
    exit(Reason).

sc_rc_tcp_client_init(Parent) ->
    put(sname, "rclient"),
    ?SEV_IPRINT("init"),
    _MRef = erlang:monitor(process, Parent),
    ok.

sc_rc_tcp_client_await_start(Parent) ->
    i("sc_rc_tcp_client_await_start -> entry"),
    ?SEV_AWAIT_START(Parent).

sc_rc_tcp_client_create(Domain, Proto) ->
    i("sc_rc_tcp_client_create -> entry"),
    case socket:open(Domain, stream, Proto) of
        {ok, Sock} ->
            case socket:getopt(Sock, otp, fd) of
                {ok, FD} ->
                    put(sname, f("rclient-~w", [FD])); % Update SName
                _ ->
                    ok
            end,
            Sock;
        {error, Reason} ->
            exit({open_failed, Reason})
    end.

sc_rc_tcp_client_bind(Sock, Domain) ->
    i("sc_rc_tcp_client_bind -> entry"),
    LSA = which_local_socket_addr(Domain),
    case socket:bind(Sock, LSA) of
        {ok, _} ->
            case socket:sockname(Sock) of
                {ok, #{family := local, path := Path}} ->
                    Path;
                {ok, _} ->
                    undefined;
                {error, Reason1} ->
                    exit({sockname, Reason1})
            end;
        {error, Reason} ->
            exit({bind, Reason})
    end.

sc_rc_tcp_client_announce_ready(Parent, Slogan) ->
    ?SEV_IPRINT("ready ~w", [Slogan]),
    ?SEV_ANNOUNCE_READY(Parent, Slogan).

sc_rc_tcp_client_await_continue(Parent, Slogan) ->
    ?SEV_IPRINT("await ~w continue", [Slogan]),
    ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan).

sc_rc_tcp_client_connect(Sock, ServerSA) ->
    i("sc_rc_tcp_client_connect -> entry"),
    case socket:connect(Sock, ServerSA) of
        ok ->
            ok;
        {error, Reason} ->
            exit({connect, Reason})
    end.

sc_rc_tcp_client_close(Sock, Path) ->
    i("sc_rc_tcp_client_close -> entry"),
    case socket:close(Sock) of
        ok ->
            unlink_path(Path),
            ok;
        {error, Reason} ->
            ?SEV_EPRINT("failed closing: "
                        "~n   Reason: ~p", [Reason]),
            unlink_path(Path),
            {error, {close, Reason}}
    end.

sc_rc_tcp_client_await_terminate(Parent) ->
    i("sc_rc_tcp_client_await_terminate -> entry"),
    case ?SEV_AWAIT_TERMINATE(Parent, parent) of
        ok ->
            ok;
        {error, Reason} ->
            Reason
    end.


%% The handlers run on the same node as the server (the local node).

sc_rc_tcp_handler_start(ID, Recv, Sock) ->
    Self     = self(),
    Fun      = fun() -> sc_rc_tcp_handler(ID, Self, Recv, Sock) end,
    {Pid, _} = erlang:spawn_monitor(Fun),
    Pid.

sc_rc_tcp_handler(ID, Parent, Recv, Sock) ->
    sc_rc_tcp_handler_init(ID, socket:getopt(Sock, otp, fd), Parent),
    sc_rc_tcp_handler_await(Parent, recv),
    RecvRes = sc_rc_tcp_handler_recv(Recv, Sock),
    sc_rc_tcp_handler_announce_ready(Parent, recv, RecvRes),
    Reason = sc_rc_tcp_handler_await(Parent, terminate),
    exit(Reason).

sc_rc_tcp_handler_init(ID, {ok, FD}, Parent) ->
    put(sname, f("handler-~w:~w", [ID, FD])),
    _MRef = erlang:monitor(process, Parent),
    ?SEV_IPRINT("started"),
    ?SEV_ANNOUNCE_READY(Parent, init),
    ok.

sc_rc_tcp_handler_await(Parent, terminate) ->
    ?SEV_IPRINT("await terminate"),
    ?SEV_AWAIT_TERMINATE(Parent, tester);
sc_rc_tcp_handler_await(Parent, Slogan) ->
    ?SEV_IPRINT("await ~w", [Slogan]),
    ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan).

sc_rc_tcp_handler_recv(Recv, Sock) ->
    ?SEV_IPRINT("recv"),
    try Recv(Sock) of
        {error, closed} ->
            ok;
        {ok, _} ->
            ?SEV_IPRINT("unexpected success"),
            {error, unexpected_success};
        {error, Reason} = ERROR ->
            ?SEV_IPRINT("receive error: "
                        "~n   ~p", [Reason]),
            ERROR
    catch
        C:E:S ->
            ?SEV_IPRINT("receive failure: "
                        "~n   Class: ~p"
                        "~n   Error: ~p"
                        "~n   Stack: ~p", [C, E, S]),
            {error, {recv, C, E, S}}
    end.

sc_rc_tcp_handler_announce_ready(Parent, Slogan, Result) ->
    ?SEV_IPRINT("announce ready"),
    ?SEV_ANNOUNCE_READY(Parent, Slogan, Result),
    ok.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% remotely closed while the process is calling the recvmsg function.
%% Socket is IPv4.

sc_rc_recvmsg_response_tcp4(suite) ->
    [];
sc_rc_recvmsg_response_tcp4(doc) ->
    [];
sc_rc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_rc_recvmsg_response_tcp4,
           fun() ->
                   Recv      = fun(Sock) -> socket:recvmsg(Sock) end,
                   InitState = #{domain   => inet,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_rc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% remotely closed while the process is calling the recvmsg function.
%% Socket is IPv6.

sc_rc_recvmsg_response_tcp6(suite) ->
    [];
sc_rc_recvmsg_response_tcp6(doc) ->
    [];
sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_rc_recvmsg_response_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recvmsg(Sock) end,
                   InitState = #{domain   => inet6,
                                 protocol => tcp,
                                 recv     => Recv},
                   ok = sc_rc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is 
%% remotely closed while the process is calling the recvmsg function.
%% Socket is Unix Domain (stream) socket.

sc_rc_recvmsg_response_tcpL(suite) ->
    [];
sc_rc_recvmsg_response_tcpL(doc) ->
    [];
sc_rc_recvmsg_response_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_rc_recvmsg_response_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   Recv      = fun(Sock) -> socket:recvmsg(Sock) end,
                   InitState = #{domain   => local,
                                 protocol => default,
                                 recv     => Recv},
                   ok = sc_rc_receive_response_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is
%% remotely closed while the process is calling the recv function.
%% The remote client sends data, then shutdown(write) and then the
%% reader attempts a recv.
%% Socket is IPv4.
%%
%% To minimize the chance of "weirdness", we should really have test cases
%% where the two sides of the connection is on different machines. But for
%% now, we will make do with different VMs on the same host.
%% This would of course not work for Unix Domain sockets.
%%

sc_rs_recv_send_shutdown_receive_tcp4(suite) ->
    [];
sc_rs_recv_send_shutdown_receive_tcp4(doc) ->
    [];
sc_rs_recv_send_shutdown_receive_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(sc_rs_recv_send_shutdown_receive_tcp4,
           fun() ->
                   MsgData   = ?DATA,
                   Recv      = fun(Sock) ->
                                       socket:recv(Sock)
                               end,
                   Send      = fun(Sock, Data) ->
                                       socket:send(Sock, Data)
                               end,
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 recv   => Recv,
                                 send   => Send,
                                 data   => MsgData},
                   ok = sc_rs_send_shutdown_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is
%% remotely closed while the process is calling the recv function.
%% The remote client sends data, then shutdown(write) and then the
%% reader attempts a recv.
%% Socket is IPv6.

sc_rs_recv_send_shutdown_receive_tcp6(suite) ->
    [];
sc_rs_recv_send_shutdown_receive_tcp6(doc) ->
    [];
sc_rs_recv_send_shutdown_receive_tcp6(_Config) when is_list(_Config) ->
    tc_try(sc_rs_recv_send_shutdown_receive_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(10)),
                   MsgData   = ?DATA,
                   Recv      = fun(Sock) ->
                                       socket:recv(Sock)
                               end,
                   Send      = fun(Sock, Data) ->
                                       socket:send(Sock, Data)
                               end,
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 recv   => Recv,
                                 send   => Send,
                                 data   => MsgData},
                   ok = sc_rs_send_shutdown_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is
%% remotely closed while the process is calling the recv function.
%% The remote client sends data, then shutdown(write) and then the
%% reader attempts a recv.
%% Socket is Unix Domain (stream) socket.

sc_rs_recv_send_shutdown_receive_tcpL(suite) ->
    [];
sc_rs_recv_send_shutdown_receive_tcpL(doc) ->
    [];
sc_rs_recv_send_shutdown_receive_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_rs_recv_send_shutdown_receive_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   MsgData   = ?DATA,
                   Recv      = fun(Sock) ->
                                       socket:recv(Sock)
                               end,
                   Send      = fun(Sock, Data) ->
                                       socket:send(Sock, Data)
                               end,
                   InitState = #{domain => local,
                                 proto  => default,
                                 recv   => Recv,
                                 send   => Send,
                                 data   => MsgData},
                   ok = sc_rs_send_shutdown_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

sc_rs_send_shutdown_receive_tcp(InitState) ->
    %% The connection is handled by a handler processes.
    %% This are created (on the fly) and handled internally
    %% by the server!
    ServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           i("get local address for ~p", [Domain]),
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain, proto := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{domain   := local,
                         lsock    := LSock,
                         local_sa := LSA} = _State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, _Port} ->
                                   ok; % We do not care about the port for local
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{lsock := LSock, local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("bound to port: ~w", [Port]),
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain := local,
                         tester := Tester, local_sa := LSA}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, LSA),
                           ok;
                      (#{tester := Tester, local_sa := LSA, lport := Port}) ->
                           ServerSA = LSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "accept",
           cmd  => fun(#{lsock := LSock, recv := Recv} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   ?SEV_IPRINT("accepted: try start handler"),
                                   Handler =
                                       sc_rs_tcp_handler_start(Recv, Sock),
                                   ?SEV_IPRINT("handler started"),
                                   {ok, State#{csock   => Sock,
                                               handler => Handler}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await handler ready (init)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = _State) ->
                           ?SEV_AWAIT_READY(Handler, handler, init,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         #{desc => "await continue (first recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "order handler to receive (first)",
           cmd  => fun(#{handler := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await ready from handler (first recv)",
           cmd  => fun(#{tester := Tester, handler := Pid} = _State) ->
                           case ?SEV_AWAIT_READY(Pid, handler, recv,
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   ?SEV_IPRINT("first recv: ~p", [Result]),
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (first recv)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv),
                           ok
                   end},
         #{desc => "await continue (second recv)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv)
                   end},
         #{desc => "order handler to receive (second)",
           cmd  => fun(#{handler := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await ready from handler (second recv)",
           cmd  => fun(#{tester := Tester, handler := Pid} = _State) ->
                           case ?SEV_AWAIT_READY(Pid, handler, recv,
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   ?SEV_IPRINT("second recv: ~p", [Result]),
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (second recv)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order handler to terminate",
           cmd  => fun(#{handler := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await handler termination",
           cmd  => fun(#{handler := Pid} = State) ->
                           ?SEV_AWAIT_TERMINATION(Pid),
                           State1 = maps:remove(csock,   State),
                           State2 = maps:remove(handler, State1),
                           {ok, State2}
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{domain   := local,
                         lsock    := Sock,
                         local_sa := #{path := Path}} = State) ->
                           socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() ->
                                                   maps:remove(local_sa, State)
                                           end,
                                           fun() -> State end),
                           {ok, maps:remove(lsock, State1)};
                      (#{lsock := LSock} = State) ->
                           case socket:close(LSock) of
                               ok ->
                                   {ok, maps:remove(lsock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, ServerSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester, 
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "create node",
           cmd  => fun(#{host := Host} = State) ->
                           case start_node(Host, client) of
                               {ok, Node} ->
                                   ?SEV_IPRINT("client node ~p started",
                                               [Node]),
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor client node",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "start remote client on client node",
           cmd  => fun(#{node := Node,
                         send := Send} = State) ->
                           Pid = sc_rs_tcp_client_start(Node, Send),
                           ?SEV_IPRINT("client ~p started", [Pid]),
                           {ok, State#{rclient => Pid}}
                   end},
         #{desc => "monitor remote client",
           cmd  => fun(#{rclient := Pid}) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "order remote client to start",
           cmd  => fun(#{rclient   := Client,
                         proto     := Proto,
                         server_sa := ServerSA}) ->
                           ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}),
                           ok
                   end},
         #{desc => "await remote client ready",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, init, 
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect, 
                                               [{rclient, Client}]),
                           ok
                   end},
         #{desc => "order remote client to continue (connect)",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, connect),
                           ok
                   end},
         #{desc => "await client process ready (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, connect,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         #{desc => "await continue (send)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, send,
                                                    [{rclient, Client}]) of
                               {ok, Data} ->
                                   {ok, State#{rclient_data => Data}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to send",
           cmd  => fun(#{rclient      := Client,
                         rclient_data := Data}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Data),
                           ok
                   end},
         #{desc => "await remote client ready (closed)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, send,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (send)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send),
                           ok
                   end},


         #{desc => "await continue (shutdown)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, shutdown,
                                               [{rclient, Client}]),
                           ok
                   end},
         #{desc => "order remote client to shutdown",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, shutdown),
                           ok
                   end},
         #{desc => "await remote client ready (shiutdown)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, shutdown,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (shutdown)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, shutdown),
                           ok
                   end},

         #{desc => "await continue (close)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, close,
                                               [{rclient, Client}]),
                           ok
                   end},
         #{desc => "order remote client to close",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, close),
                           ok
                   end},
         #{desc => "await remote client ready (closed)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, close,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (close)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, close),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester,
                                                     [{rclient, Client}]) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "kill remote client",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await remote client termination",
           cmd  => fun(#{rclient := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(rclient, State),
                           {ok, State1}
                   end},
         #{desc => "stop client node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await client node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   State1 = maps:remove(node_id, State),
                                   State2 = maps:remove(node,    State1),
                                   {ok, State2}
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},

         %% Start the client(s)
         #{desc => "order client start",
           cmd  => fun(#{client    := Pid,
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, ServerSA),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},

         %% The actual test
         #{desc => "order server continue (accept)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, connect,
                                            [{server, Server}]),
                           ok
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept,
                                            [{client, Client}]),
                           ok
                   end},

         #{desc => "order client continue (send)",
           cmd  => fun(#{client := Pid,
                         data   := Data} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send, Data),
                           ok
                   end},
         #{desc => "await client ready (send)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, send,
                                            [{server, Server}]),
                           ok
                   end},

         #{desc => "order client continue (shutdown)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, shutdown),
                           ok
                   end},
         #{desc => "await client ready (shutdown)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, shutdown,
                                            [{server, Server}]),
                           ok
                   end},

         #{desc => "order server continue (first recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await server ready (first recv)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, recv,
                                            [{client, Client}]),
                           ok
                   end},

         #{desc => "order server continue (second recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         #{desc => "await server ready (second recv)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, recv,
                                            [{client, Client}]),
                           ok
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "order client continue (close)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await client ready (close)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, close,
                                            [{server, Server}]),
                           ok
                   end},

         %% Terminations
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    ServerInitState = #{domain => maps:get(domain, InitState),
                        proto  => maps:get(proto,  InitState),
                        recv   => maps:get(recv,   InitState)},
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator"),
    ClientInitState = #{host   => local_host(),
                        domain => maps:get(domain, InitState),
                        proto  => maps:get(proto,  InitState),
                        send   => maps:get(send, InitState)},
    Client = ?SEV_START("client", ClientSeq, ClientInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid,
                        data   => maps:get(data, InitState)},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).


sc_rs_tcp_client_start(Node, Send) ->
    Self = self(),
    Fun  = fun() -> sc_rs_tcp_client(Self, Send) end,
    erlang:spawn(Node, Fun).


sc_rs_tcp_client(Parent, Send) ->
    sc_rs_tcp_client_init(Parent),
    {ServerSA, Proto} = sc_rs_tcp_client_await_start(Parent),
    Domain   = maps:get(family, ServerSA),
    Sock     = sc_rs_tcp_client_create(Domain, Proto),
    Path     = sc_rs_tcp_client_bind(Sock, Domain),
    sc_rs_tcp_client_announce_ready(Parent, init),
    sc_rs_tcp_client_await_continue(Parent, connect),
    sc_rs_tcp_client_connect(Sock, ServerSA),
    sc_rs_tcp_client_announce_ready(Parent, connect),
    Data = sc_rs_tcp_client_await_continue(Parent, send),
    sc_rs_tcp_client_send(Sock, Send, Data),
    sc_rs_tcp_client_announce_ready(Parent, send),
    sc_rs_tcp_client_await_continue(Parent, shutdown),
    sc_rs_tcp_client_shutdown(Sock),
    sc_rs_tcp_client_announce_ready(Parent, shutdown),
    sc_rs_tcp_client_await_continue(Parent, close),
    sc_rs_tcp_client_close(Sock, Path),
    sc_rs_tcp_client_announce_ready(Parent, close),
    Reason = sc_rs_tcp_client_await_terminate(Parent),
    ?SEV_IPRINT("terminate"),
    exit(Reason).

sc_rs_tcp_client_init(Parent) ->
    put(sname, "rclient"),
    ?SEV_IPRINT("init"),
    _MRef = erlang:monitor(process, Parent),
    ok.

sc_rs_tcp_client_await_start(Parent) ->
    i("sc_rs_tcp_client_await_start -> entry"),
    ?SEV_AWAIT_START(Parent).

sc_rs_tcp_client_create(Domain, Proto) ->
    i("sc_rs_tcp_client_create -> entry"),
    case socket:open(Domain, stream, Proto) of
        {ok, Sock} ->
            Sock;
        {error, Reason} ->
            exit({open_failed, Reason})
    end.

sc_rs_tcp_client_bind(Sock, Domain) ->
    i("sc_rs_tcp_client_bind -> entry"),
    LSA = which_local_socket_addr(Domain),
    case socket:bind(Sock, LSA) of
        {ok, _} ->
            case socket:sockname(Sock) of
                {ok, #{family := local, path := Path}} ->
                    Path;
                {ok, _} ->
                    undefined;
                {error, Reason1} ->
                    exit({sockname, Reason1})
            end;
        {error, Reason} ->
            exit({bind, Reason})
    end.

sc_rs_tcp_client_announce_ready(Parent, Slogan) ->
    ?SEV_ANNOUNCE_READY(Parent, Slogan).

sc_rs_tcp_client_await_continue(Parent, Slogan) ->
    i("sc_rs_tcp_client_await_continue -> entry"),
    case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of
        ok ->
            ok;
        {ok, Extra} ->
            Extra;
        {error, Reason} ->
            exit({await_continue, Slogan, Reason})
    end.


sc_rs_tcp_client_connect(Sock, ServerSA) ->
    i("sc_rs_tcp_client_connect -> entry"),
    case socket:connect(Sock, ServerSA) of
        ok ->
            ok;
        {error, Reason} ->
            exit({connect, Reason})
    end.

sc_rs_tcp_client_send(Sock, Send, Data) ->
    i("sc_rs_tcp_client_send -> entry"),
    case Send(Sock, Data) of
        ok ->
            ok;
        {error, Reason} ->
            exit({send, Reason})
    end.

sc_rs_tcp_client_shutdown(Sock) ->
    i("sc_rs_tcp_client_shutdown -> entry"),
    case socket:shutdown(Sock, write) of
        ok ->
            ok;
        {error, Reason} ->
            exit({shutdown, Reason})
    end.

sc_rs_tcp_client_close(Sock, Path) ->
    i("sc_rs_tcp_client_close -> entry"),
    case socket:close(Sock) of
        ok ->
            unlink_path(Path),
            ok;
        {error, Reason} ->
            ?SEV_EPRINT("failed closing: "
                        "~n   Reason: ~p", [Reason]),
            unlink_path(Path),
            {error, {close, Reason}}
    end.

sc_rs_tcp_client_await_terminate(Parent) ->
    i("sc_rs_tcp_client_await_terminate -> entry"),
    case ?SEV_AWAIT_TERMINATE(Parent, parent) of
        ok ->
            ok;
        {error, Reason} ->
            Reason
    end.


%% The handlers run on the same node as the server (the local node).

sc_rs_tcp_handler_start(Recv, Sock) ->
    Self     = self(),
    Fun      = fun() -> sc_rs_tcp_handler(Self, Recv, Sock) end,
    {Pid, _} = erlang:spawn_monitor(Fun),
    Pid.

sc_rs_tcp_handler(Parent, Recv, Sock) ->
    sc_rs_tcp_handler_init(Parent),
    sc_rs_tcp_handler_await(Parent, recv),
    ok = sc_rs_tcp_handler_recv(Recv, Sock, true),
    sc_rs_tcp_handler_announce_ready(Parent, recv, received),
    sc_rs_tcp_handler_await(Parent, recv),
    ok = sc_rs_tcp_handler_recv(Recv, Sock, false),
    sc_rs_tcp_handler_announce_ready(Parent, recv, closed),
    Reason = sc_rs_tcp_handler_await(Parent, terminate),
    exit(Reason).

sc_rs_tcp_handler_init(Parent) ->
    put(sname, "handler"),
    _MRef = erlang:monitor(process, Parent),
    ?SEV_IPRINT("started"),
    ?SEV_ANNOUNCE_READY(Parent, init),
    ok.

sc_rs_tcp_handler_await(Parent, terminate) ->
    ?SEV_IPRINT("await terminate"),
    ?SEV_AWAIT_TERMINATE(Parent, tester);
sc_rs_tcp_handler_await(Parent, Slogan) ->
    ?SEV_IPRINT("await ~w", [Slogan]),
    ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan).

%% This hould actually work - we leave it for now
sc_rs_tcp_handler_recv(Recv, Sock, First) ->
    ?SEV_IPRINT("recv"),
    try Recv(Sock) of
        {ok, _} when (First =:= true) ->
            ok;
        {error, closed} when (First =:= false) ->
            ok;
        {ok, _} ->
            ?SEV_IPRINT("unexpected success"),
            {error, unexpected_success};
        {error, Reason} = ERROR ->
            ?SEV_IPRINT("receive error: "
                        "~n   ~p", [Reason]),
            ERROR
    catch
        C:E:S ->
            ?SEV_IPRINT("receive failure: "
                        "~n   Class: ~p"
                        "~n   Error: ~p"
                        "~n   Stack: ~p", [C, E, S]),
            {error, {recv, C, E, S}}
    end.

sc_rs_tcp_handler_announce_ready(Parent, Slogan, Result) ->
    ?SEV_IPRINT("announce ready"),
    ?SEV_ANNOUNCE_READY(Parent, Slogan, Result),
    ok.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is
%% remotely closed while the process is calling the recvmsg function.
%% The remote client sends data, then shutdown(write) and then the
%% reader attempts a recv.
%% Socket is IPv4.

sc_rs_recvmsg_send_shutdown_receive_tcp4(suite) ->
    [];
sc_rs_recvmsg_send_shutdown_receive_tcp4(doc) ->
    [];
sc_rs_recvmsg_send_shutdown_receive_tcp4(_Config) when is_list(_Config) ->
    tc_try(sc_rs_recvmsg_send_shutdown_receive_tcp4,
           fun() ->
                   ?TT(?SECS(30)),
                   MsgData   = ?DATA,
                   Recv      = fun(Sock) ->
                                       case socket:recvmsg(Sock) of
                                           {ok, #{addr  := undefined,
                                                  iov   := [Data]}} ->
                                               {ok, Data};
                                           {error, _} = ERROR ->
                                               ERROR
                                       end
                               end,
                   Send      = fun(Sock, Data) when is_binary(Data) ->
                                  MsgHdr = #{iov => [Data]},
                                  socket:sendmsg(Sock, MsgHdr)
                               end,
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 recv   => Recv,
                                 send   => Send,
                                 data   => MsgData},
                   ok = sc_rs_send_shutdown_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is
%% remotely closed while the process is calling the recvmsg function.
%% The remote client sends data, then shutdown(write) and then the
%% reader attempts a recv.
%% Socket is IPv6.

sc_rs_recvmsg_send_shutdown_receive_tcp6(suite) ->
    [];
sc_rs_recvmsg_send_shutdown_receive_tcp6(doc) ->
    [];
sc_rs_recvmsg_send_shutdown_receive_tcp6(_Config) when is_list(_Config) ->
    tc_try(sc_rs_recvmsg_send_shutdown_receive_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(10)),
                   MsgData   = ?DATA,
                   Recv      = fun(Sock) ->
                                       case socket:recvmsg(Sock) of
                                           {ok, #{addr  := undefined,
                                                  iov   := [Data]}} ->
                                               {ok, Data};
                                           {error, _} = ERROR ->
                                               ERROR
                                       end
                               end,
                   Send      = fun(Sock, Data) when is_binary(Data) ->
                                       MsgHdr = #{iov => [Data]},
                                       socket:sendmsg(Sock, MsgHdr)
                               end,
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 recv   => Recv,
                                 send   => Send,
                                 data   => MsgData},
                   ok = sc_rs_send_shutdown_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test what happens when a socket is
%% remotely closed while the process is calling the recvmsg function.
%% The remote client sends data, then shutdown(write) and then the
%% reader attempts a recv.
%% Socket is UNix Domain (stream) socket.

sc_rs_recvmsg_send_shutdown_receive_tcpL(suite) ->
    [];
sc_rs_recvmsg_send_shutdown_receive_tcpL(doc) ->
    [];
sc_rs_recvmsg_send_shutdown_receive_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(sc_rs_recvmsg_send_shutdown_receive_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   {ok, CWD} = file:get_cwd(),
                   ?SEV_IPRINT("CWD: ~s", [CWD]),
                   MsgData   = ?DATA,
                   Recv      = fun(Sock) ->
                                       case socket:recvmsg(Sock) of
                                           %% On some platforms, the address
                                           %% is *not* provided (e.g. FreeBSD)
                                           {ok, #{addr  := undefined,
                                                  iov   := [Data]}} ->
                                               {ok, Data};
                                           %% On some platforms, the address
                                           %% *is* provided (e.g. linux)
                                           {ok, #{addr  := #{family := local},
                                                  iov   := [Data]}} ->
                                               {ok, Data};
                                           {error, _} = ERROR ->
                                               ERROR
                                       end
                               end,
                   Send      = fun(Sock, Data) when is_binary(Data) ->
                                       MsgHdr = #{iov => [Data]},
                                       socket:sendmsg(Sock, MsgHdr)
                               end,
                   InitState = #{domain => local,
                                 proto  => default,
                                 recv   => Recv,
                                 send   => Send,
                                 data   => MsgData},
                   ok = sc_rs_send_shutdown_receive_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% behave as expected when sending and/or reading chunks.
%% First send data in one "big" chunk, and read it in "small" chunks.
%% Second, send in a bunch of "small" chunks, and read in one "big" chunk.
%% Socket is IPv4.

traffic_send_and_recv_chunks_tcp4(suite) ->
    [];
traffic_send_and_recv_chunks_tcp4(doc) ->
    [];
traffic_send_and_recv_chunks_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(traffic_send_and_recv_chunks_tcp4,
           fun() ->
                   InitState = #{domain => inet,
                                 proto  => tcp},
                   ok = traffic_send_and_recv_chunks_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% behave as expected when sending and/or reading chunks.
%% First send data in one "big" chunk, and read it in "small" chunks.
%% Second, send in a bunch of "small" chunks, and read in one "big" chunk.
%% Socket is IPv6.

traffic_send_and_recv_chunks_tcp6(suite) ->
    [];
traffic_send_and_recv_chunks_tcp6(doc) ->
    [];
traffic_send_and_recv_chunks_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(traffic_send_and_recv_chunks_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6,
                                 proto  => tcp},
                   ok = traffic_send_and_recv_chunks_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% behave as expected when sending and/or reading chunks.
%% First send data in one "big" chunk, and read it in "small" chunks.
%% Second, send in a bunch of "small" chunks, and read in one "big" chunk.
%% Socket is UNix Domain (Stream) socket.

traffic_send_and_recv_chunks_tcpL(suite) ->
    [];
traffic_send_and_recv_chunks_tcpL(doc) ->
    [];
traffic_send_and_recv_chunks_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(traffic_send_and_recv_chunks_tcp6,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default},
                   ok = traffic_send_and_recv_chunks_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

traffic_send_and_recv_chunks_tcp(InitState) ->
    ServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain, proto := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{domain   := local,
                         lsock    := LSock,
                         local_sa := LSA} = _State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, _Port} ->
                                   ok; % We do not care about the port for local
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{lsock    := LSock,
                         local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain   := local,
                         tester   := Tester,
                         local_sa := LSA}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, LSA),
                           ok;
                      (#{tester   := Tester,
                         local_sa := LSA,
                         lport    := Port}) ->
                           ServerSA = LSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "accept",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   {ok, State#{csock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         #{desc => "await continue (recv-many-small)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_many_small)
                   end},
         #{desc => "recv chunk 1",
           cmd  => fun(#{csock := Sock} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 1 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 2",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 2 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 3",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 3 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 4",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 4 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 5",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 5 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 6",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 6 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 7",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 7 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 8",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 8 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 9",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 9 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv chunk 10",
           cmd  => fun(#{csock  := Sock,
                         chunks := Chunks} = State) ->
                           case socket:recv(Sock, 100) of
                               {ok, Chunk} ->
                                   ?SEV_IPRINT("recv of chunk 10 of ~p bytes",
                                               [size(Chunk)]),
                                   {ok, State#{chunks => [b2l(Chunk)|Chunks]}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv-many-small)",
           cmd  => fun(#{tester := Tester,
                         chunks := Chunks} = State) ->
                           Data = lists:flatten(lists:reverse(Chunks)),
                           ?SEV_ANNOUNCE_READY(Tester, recv_many_small, Data),
                           {ok, maps:remove(chunks, State)}
                   end},

         #{desc => "await continue (recv-one-big)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester, recv_one_big) of
                               {ok, Size} ->
                                   {ok, State#{size => Size}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "recv (one big)",
           cmd  => fun(#{tester := Tester, csock := Sock, size := Size} = _State) ->
                           %% socket:setopt(Sock, otp, debug, true),
                           case socket:recv(Sock, Size) of
                               {ok, Data} ->
                                   ?SEV_ANNOUNCE_READY(Tester,
                                                       recv_one_big,
                                                       b2l(Data)),
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "close connection socket (just in case)",
           cmd  => fun(#{csock := Sock} = State) ->
                           (catch socket:close(Sock)),
                           {ok, maps:remove(csock, State)}
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{domain   := local,
                         lsock    := Sock,
                         local_sa := #{path := Path}} = State) ->
                           ok = socket:close(Sock),
                           State1 =
                               unlink_path(Path,
                                           fun() ->
                                                   maps:remove(local_sa, State)
                                           end,
                                           fun() -> State end),
                           {ok, maps:remove(lsock, State1)};
                      (#{lsock := Sock} = State) ->
                           (catch socket:close(Sock)),
                           {ok, maps:remove(lsock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, ServerSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester,
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "create node",
           cmd  => fun(#{host := Host} = State) ->
                           case start_node(Host, client) of
                               {ok, Node} ->
                                   ?SEV_IPRINT("(remote) client node ~p started",
                                               [Node]),
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor client node",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "start remote client",
           cmd  => fun(#{node := Node} = State) ->
                           Pid = traffic_snr_tcp_client_start(Node),
                           ?SEV_IPRINT("client ~p started", [Pid]),
                           {ok, State#{rclient => Pid}}
                   end},
         #{desc => "monitor remote client",
           cmd  => fun(#{rclient := Pid}) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "order remote client to start",
           cmd  => fun(#{rclient   := Client,
                         server_sa := ServerSA,
                         proto     := Proto}) ->
                           ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}),
                           ok
                   end},
         #{desc => "await remote client ready",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, init,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect,
                                               [{rclient, Client}]),
                           ok
                   end},
         #{desc => "order remote client to continue (connect)",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, connect),
                           ok
                   end},
         #{desc => "await client process ready (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, rclient, connect,
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},

         #{desc => "await continue (send-one-big)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester,
                                                    send_one_big,
                                                    [{rclient, Client}]) of
                               {ok, Data} ->
                                   {ok, State#{data => Data}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send)",
           cmd  => fun(#{rclient := Client, data := Data}) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Data),
                           ok
                   end},
         #{desc => "await client process ready (send)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send,
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (send-one-big)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_one_big),
                           ok
                   end},

         #{desc => "await continue (send-many-small)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = State) ->
                           case ?SEV_AWAIT_CONTINUE(Tester, tester,
                                                    send_many_small,
                                                    [{rclient, Client}]) of
                               {ok, Data} ->
                                   {ok, State#{data => Data}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 1)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 1: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 1)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 2)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 2: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 2)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 3)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 3: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 3)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 4)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 4: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 4)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 5)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 5: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 5)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 6)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 6: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 6)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 7)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 7: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 7)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 8)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 8: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 8)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 9)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, RestData} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 9: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, State#{data => RestData}}
                   end},
         #{desc => "await client process ready (send chunk 9)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send chunk 10)",
           cmd  => fun(#{rclient := Client,
                         data    := Data} = State) ->
                           {Chunk, []} = lists:split(100, Data),
                           %% ?SEV_IPRINT("order send of chunk 10: "
                           %%             "~n   Size: ~p"
                           %%             "~n   ~p", [length(Chunk), Chunk]),
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, Chunk),
                           {ok, maps:remove(data, State)}
                   end},
         #{desc => "await client process ready (send chunk 10)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order remote client to continue (send stop)",
           cmd  => fun(#{rclient := Client} = State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send, stop),
                           {ok, maps:remove(data, State)}
                   end},
         #{desc => "await client process ready (send stop)",
           cmd  => fun(#{tester  := Tester,
                         rclient := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Client, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   Result;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (send-many-small)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_many_small),
                           ok
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester  := Tester, 
                         rclient := Client} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester,
                                                     [{rclient, Client}]) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "kill remote client",
           cmd  => fun(#{rclient := Client}) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await remote client termination",
           cmd  => fun(#{rclient := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(rclient, State),
                           {ok, State1}
                   end},
         #{desc => "stop client node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await client node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   {ok, maps:remove(node, State)}
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client    := Pid, 
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, ServerSA),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},
 
         %% The actual test
         #{desc => "order server continue (accept)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept,
                                            [{client, Client}]),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, connect, 
                                            [{server, Server}])
                   end},

         #{desc => "generate data",
           cmd  => fun(State) ->
                           D1 = lists:seq(1,250),
                           D2 = lists:duplicate(4, D1),
                           D3 = lists:flatten(D2),
                           {ok, State#{data => D3}}
                   end},

         %% (client) Send one big and (server) recv may small
         #{desc => "order server continue (recv-many-small)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv_many_small),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (send-one-big)",
           cmd  => fun(#{client := Pid, data := Data} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send_one_big, Data),
                           ok
                   end},
         #{desc => "await client ready (send-one-big)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ok = ?SEV_AWAIT_READY(Client, client, send_one_big, 
                                                 [{server, Server}])
                   end},
         #{desc => "await server ready (recv-many-small)",
           cmd  => fun(#{server := Server,
                         client := Client, 
                         data   := Data} = _State) ->
                           case ?SEV_AWAIT_READY(Server, server, recv_many_small,
                                                 [{client, Client}]) of
                               {ok, Data} ->
                                   ok;
                               {ok, OtherData} ->
                                   {error, {mismatched_data, Data, OtherData}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "order server continue (recv-one-big)",
           cmd  => fun(#{server := Pid, data := Data} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv_one_big, length(Data)),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (send-many-small)",
           cmd  => fun(#{client := Pid, data := Data} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send_many_small, Data),
                           ok
                   end},
         #{desc => "await client ready (send-many-small)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ok = ?SEV_AWAIT_READY(Client, client, send_many_small, 
                                                 [{server, Server}])
                   end},
         #{desc => "await server ready (recv-one-big)",
           cmd  => fun(#{server := Server,
                         client := Client, 
                         data   := Data} = State) ->
                           case ?SEV_AWAIT_READY(Server, server, recv_one_big,
                                                 [{client, Client}]) of
                               {ok, Data} ->
                                   {ok, maps:remove(data, State)};
                               {ok, OtherData} ->
                                   {error, {mismatched_data, Data, OtherData}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         %% Terminations
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    ServerInitState = InitState,
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator(s)"),
    ClientInitState = InitState#{host => local_host()},
    Client = ?SEV_START("client", ClientSeq, ClientInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).
    


traffic_snr_tcp_client_start(Node) ->
    Self = self(),
    Fun  = fun() -> traffic_snr_tcp_client(Self) end,
    erlang:spawn(Node, Fun).

traffic_snr_tcp_client(Parent) ->
    {Sock, ServerSA, Path} = traffic_snr_tcp_client_init(Parent),
    traffic_snr_tcp_client_announce_ready(Parent, init),
    traffic_snr_tcp_client_await_continue(Parent, connect),
    traffic_snr_tcp_client_connect(Sock, ServerSA),
    traffic_snr_tcp_client_announce_ready(Parent, connect),
    traffic_snr_tcp_client_send_loop(Parent, Sock),
    Reason = traffic_snr_tcp_client_await_terminate(Parent),
    traffic_snr_tcp_client_close(Sock, Path),
    exit(Reason).


traffic_snr_tcp_client_send_loop(Parent, Sock) ->
    case ?SEV_AWAIT_CONTINUE(Parent, parent, send) of
        {ok, stop} -> % Breakes the loop
            ?SEV_ANNOUNCE_READY(Parent, send, ok),
            ok;
        {ok, Data} ->
            case socket:send(Sock, Data) of
                ok ->
                    ?SEV_ANNOUNCE_READY(Parent, send, ok),
                    traffic_snr_tcp_client_send_loop(Parent, Sock);
                {error, Reason} = ERROR ->
                    ?SEV_ANNOUNCE_READY(Parent, send, ERROR),
                    exit({send, Reason})
            end;
        {error, Reason} ->
            exit({await_continue, Reason})
    end.

traffic_snr_tcp_client_init(Parent) ->
    put(sname, "rclient"),
    ?SEV_IPRINT("init"),
    _MRef = erlang:monitor(process, Parent),
    {ServerSA, Proto} = traffic_snr_tcp_client_await_start(Parent),
    Domain   = maps:get(family, ServerSA),
    Sock     = traffic_snr_tcp_client_create(Domain, Proto),
    Path     = traffic_snr_tcp_client_bind(Sock, Domain),
    {Sock, ServerSA, Path}.

traffic_snr_tcp_client_await_start(Parent) ->
    i("traffic_snr_tcp_client_await_start -> entry"),
    ?SEV_AWAIT_START(Parent).

traffic_snr_tcp_client_create(Domain, Proto) ->
    i("traffic_snr_tcp_client_create -> entry"),
    case socket:open(Domain, stream, Proto) of
        {ok, Sock} ->
            Sock;
        {error, Reason} ->
            exit({open_failed, Reason})
    end.

traffic_snr_tcp_client_bind(Sock, Domain) ->
    i("traffic_snr_tcp_client_bind -> entry"),
    LSA = which_local_socket_addr(Domain),
    case socket:bind(Sock, LSA) of
        {ok, _} ->
            case socket:sockname(Sock) of
                {ok, #{family := local, path := Path}} ->
                    Path;
                {ok, _} ->
                    undefined;
                {error, Reason1} ->
                    exit({sockname, Reason1})
            end;
        {error, Reason} ->
            exit({bind, Reason})
    end.

traffic_snr_tcp_client_announce_ready(Parent, Slogan) ->
    ?SEV_ANNOUNCE_READY(Parent, Slogan).

traffic_snr_tcp_client_await_continue(Parent, Slogan) ->
    i("traffic_snr_tcp_client_await_continue -> entry"),
    ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan).

traffic_snr_tcp_client_connect(Sock, ServerSA) ->
    i("traffic_snr_tcp_client_connect -> entry"),
    case socket:connect(Sock, ServerSA) of
        ok ->
            ok;
        {error, Reason} ->
            exit({connect, Reason})
    end.

traffic_snr_tcp_client_close(Sock, Path) ->
    i("traffic_snr_tcp_client_close -> entry"),
    case socket:close(Sock) of
        ok ->
            unlink_path(Path),
            ok;
        {error, Reason} ->
            ?SEV_EPRINT("failed closing: "
                        "~n   Reason: ~p", [Reason]),
            unlink_path(Path),
            {error, {close, Reason}}
    end.

traffic_snr_tcp_client_await_terminate(Parent) ->
    i("traffic_snr_tcp_client_await_terminate -> entry"),
    case ?SEV_AWAIT_TERMINATE(Parent, parent) of
        ok ->
            ok;
        {error, Reason} ->
            Reason
    end.



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.

traffic_ping_pong_small_send_and_recv_tcp4(suite) ->
    [];
traffic_ping_pong_small_send_and_recv_tcp4(doc) ->
    [];
traffic_ping_pong_small_send_and_recv_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_send_and_recv_tcp4,
           fun() ->
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.

traffic_ping_pong_small_send_and_recv_tcp6(suite) ->
    [];
traffic_ping_pong_small_send_and_recv_tcp6(doc) ->
    [];
traffic_ping_pong_small_send_and_recv_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_send_and_recv_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (stream) socket.

traffic_ping_pong_small_send_and_recv_tcpL(suite) ->
    [];
traffic_ping_pong_small_send_and_recv_tcpL(doc) ->
    [];
traffic_ping_pong_small_send_and_recv_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_send_and_recv_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.

traffic_ping_pong_medium_send_and_recv_tcp4(suite) ->
    [];
traffic_ping_pong_medium_send_and_recv_tcp4(doc) ->
    [];
traffic_ping_pong_medium_send_and_recv_tcp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_send_and_recv_tcp4,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.

traffic_ping_pong_medium_send_and_recv_tcp6(suite) ->
    [];
traffic_ping_pong_medium_send_and_recv_tcp6(doc) ->
    [];
traffic_ping_pong_medium_send_and_recv_tcp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_send_and_recv_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (stream) socket.

traffic_ping_pong_medium_send_and_recv_tcpL(suite) ->
    [];
traffic_ping_pong_medium_send_and_recv_tcpL(doc) ->
    [];
traffic_ping_pong_medium_send_and_recv_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_send_and_recv_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv4.

traffic_ping_pong_large_send_and_recv_tcp4(suite) ->
    [];
traffic_ping_pong_large_send_and_recv_tcp4(doc) ->
    [];
traffic_ping_pong_large_send_and_recv_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(45)),
    Msg = l2b(?TPP_LARGE),
    Num = ?TPP_LARGE_NUM,
    tc_try(traffic_ping_pong_large_send_and_recv_tcp4,
           fun() ->
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv6.

traffic_ping_pong_large_send_and_recv_tcp6(suite) ->
    [];
traffic_ping_pong_large_send_and_recv_tcp6(doc) ->
    [];
traffic_ping_pong_large_send_and_recv_tcp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_LARGE),
    Num = ?TPP_LARGE_NUM,
    tc_try(traffic_ping_pong_large_send_and_recv_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(45)),
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the send and recv functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for UNix Domain (stream) socket.

traffic_ping_pong_large_send_and_recv_tcpL(suite) ->
    [];
traffic_ping_pong_large_send_and_recv_tcpL(doc) ->
    [];
traffic_ping_pong_large_send_and_recv_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(45)),
    Msg = l2b(?TPP_LARGE),
    Num = ?TPP_LARGE_NUM,
    tc_try(traffic_ping_pong_large_send_and_recv_tcpL,
           fun() ->
                   has_support_unix_domain_socket(),
                   traffic_ping_pong_large_host_cond()
           end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_send_and_recv_tcp(InitState)
           end).

%% This test case is a bit extreme and fails on some hosts
%% (e.g. OpenIndiana Hipster), so exclude them.
traffic_ping_pong_large_host_cond() ->
    traffic_ping_pong_large_host_cond(os:type(), os:version()).

traffic_ping_pong_large_host_cond({unix, sunos}, _) ->
    skip("TC does not work on platform");
traffic_ping_pong_large_host_cond(_, _) ->
    ok.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendto and recvfrom 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for two different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.

traffic_ping_pong_small_sendto_and_recvfrom_udp4(suite) ->
    [];
traffic_ping_pong_small_sendto_and_recvfrom_udp4(doc) ->
    [];
traffic_ping_pong_small_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp4,
           fun() ->
                   ?TT(?SECS(45)),
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendto and recvfrom 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for two different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.

traffic_ping_pong_small_sendto_and_recvfrom_udp6(suite) ->
    [];
traffic_ping_pong_small_sendto_and_recvfrom_udp6(doc) ->
    [];
traffic_ping_pong_small_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(45)),
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendto and recvfrom 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for two different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (dgram) socket.

traffic_ping_pong_small_sendto_and_recvfrom_udpL(suite) ->
    [];
traffic_ping_pong_small_sendto_and_recvfrom_udpL(doc) ->
    [];
traffic_ping_pong_small_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(45)),
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendto and recvfrom 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for two different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.

traffic_ping_pong_medium_sendto_and_recvfrom_udp4(suite) ->
    [];
traffic_ping_pong_medium_sendto_and_recvfrom_udp4(doc) ->
    [];
traffic_ping_pong_medium_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udp4,
           fun() ->
                   ?TT(?SECS(45)),
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendto and recvfrom 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for two different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.

traffic_ping_pong_medium_sendto_and_recvfrom_udp6(suite) ->
    [];
traffic_ping_pong_medium_sendto_and_recvfrom_udp6(doc) ->
    [];
traffic_ping_pong_medium_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(45)),
                   InitState = #{domain => inet6,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendto and recvfrom 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for two different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (dgram) socket.

traffic_ping_pong_medium_sendto_and_recvfrom_udpL(suite) ->
    [];
traffic_ping_pong_medium_sendto_and_recvfrom_udpL(doc) ->
    [];
traffic_ping_pong_medium_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   ?TT(?SECS(45)),
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.

traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(suite) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(doc) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4,
           fun() ->
                   ?TT(?SECS(20)),
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.

traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(suite) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(doc) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(20)),
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (stream) socket.

traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(suite) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(doc) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   ?TT(?SECS(20)),
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.

traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(suite) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(doc) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.

traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(suite) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(doc) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(20)),
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (stream) socket.

traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(suite) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(doc) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   ?TT(?SECS(20)),
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv4.

traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(suite) ->
    [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(doc) ->
    [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_LARGE),
    Num = ?TPP_LARGE_NUM,
    tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4,
           fun() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).


traffic_ping_pong_large_sendmsg_and_recvmsg_cond() ->
    traffic_ping_pong_large_sendmsg_and_recvmsg_cond(os:type(), os:version()).

traffic_ping_pong_large_sendmsg_and_recvmsg_cond({unix, linux}, {M, _, _})
  when (M < 3) ->
    skip("TC may not work on this version");
traffic_ping_pong_large_sendmsg_and_recvmsg_cond(_, _) ->
    ok.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv6.

traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(suite) ->
    [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(doc) ->
    [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_LARGE),
    Num = ?TPP_LARGE_NUM,
    tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6,
           fun() ->
                   has_support_ipv6(),
                   traffic_ping_pong_large_sendmsg_and_recvmsg_cond()
           end,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes), medium (8K) and large (8M).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for Unix Domain (stream) socket.

traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(suite) ->
    [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(doc) ->
    [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_LARGE),
    Num = ?TPP_LARGE_NUM,
    tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.

traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(suite) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(doc) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp4,
           fun() ->
                   ?TT(?SECS(60)),
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.

traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(suite) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(doc) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => inet6,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg functions
%% by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (dgram) socket.

traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(suite) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(doc) ->
    [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.

traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(suite) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(doc) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4,
           fun() ->
                   ?TT(?SECS(30)),
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.

traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(suite) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(doc) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ?TT(?SECS(20)),
                   InitState = #{domain => inet6,
                                 proto  => udp,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to test that the sendmsg and recvmsg 
%% functions by repeatedly sending a meassage between two entities.
%% The same basic test case is used for three different message sizes; 
%% small (8 bytes) and medium (8K).
%% The message is sent from A to B and then back again. This is 
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (dgram) socket.

traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(suite) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(doc) ->
    [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) ->
    Msg = l2b(?TPP_MEDIUM),
    Num = ?TPP_MEDIUM_NUM,
    tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   ?TT(?SECS(20)),
                   InitState = #{domain => local,
                                 proto  => default,
                                 msg    => Msg,
                                 num    => Num},
                   ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState)
           end).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Ping-Pong for TCP

traffic_ping_pong_send_and_recv_tcp(InitState) ->
    Send = fun(Sock, Data) -> socket:send(Sock, Data) end,
    Recv = fun(Sock, Sz)   -> socket:recv(Sock, Sz) end,
    InitState2 = InitState#{send => Send, % Send function
                            recv => Recv  % Receive function
                           },
    traffic_ping_pong_send_and_receive_tcp(InitState2).

traffic_ping_pong_sendmsg_and_recvmsg_tcp(#{domain := local} = InitState) ->
    Recv = fun(Sock, Sz)   -> 
                   case socket:recvmsg(Sock, Sz, 0) of
                       %% On some platforms, the address
                       %% is *not* provided (e.g. FreeBSD)
                       {ok, #{addr  := undefined,
                              iov   := [Data]}} ->
                           {ok, Data};
                       %% On some platforms, the address
                       %% *is* provided (e.g. linux)
                       {ok, #{addr  := #{family := local},
                              iov   := [Data]}} ->
                           {ok, Data};
                       {error, _} = ERROR ->
                           ERROR
                   end
           end,
    InitState2 = InitState#{recv => Recv},  % Receive function
    traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState2);
traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) ->
    Recv = fun(Sock, Sz)   -> 
                   case socket:recvmsg(Sock, Sz, 0) of
                       {ok, #{addr  := undefined,
                              iov   := [Data]}} ->
                           {ok, Data};
                       {error, _} = ERROR ->
                           ERROR
                   end
           end,
    InitState2 = InitState#{recv => Recv},  % Receive function
    traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState2).

traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState) ->
    Send = fun(Sock, Data) when is_binary(Data) ->
                   MsgHdr = #{iov => [Data]},
                   socket:sendmsg(Sock, MsgHdr);
              (Sock, Data) when is_list(Data) -> %% We assume iovec...
                   MsgHdr = #{iov => Data},
                   socket:sendmsg(Sock, MsgHdr)
           end,
    InitState2 = InitState#{send => Send}, % Send function
    traffic_ping_pong_send_and_receive_tcp(InitState2).


traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) ->
    Fun = fun(Sock) -> 
                  {ok, RcvSz} = socket:getopt(Sock, socket, rcvbuf),
		  ?SEV_IPRINT("RcvBuf is ~p (needs atleast ~p)", 
			      [RcvSz, 16+size(Msg)]),
                  if (RcvSz < size(Msg)) ->
                          case socket:setopt(Sock,
					     socket, rcvbuf, 1024+size(Msg)) of
			      ok ->
				  ok;
			      {error, enobufs} ->
				  skip({failed_change, rcvbuf});
			      {error, Reason1} ->
				  ?FAIL({rcvbuf, Reason1})
			  end;
                     true ->
                          ok
                  end,
                  {ok, SndSz} = socket:getopt(Sock, socket, sndbuf),
		  ?SEV_IPRINT("SndBuf is ~p (needs atleast ~p)", 
			      [SndSz, 16+size(Msg)]),
                  if (SndSz < size(Msg)) ->
                          case socket:setopt(Sock,
					     socket, sndbuf, 1024+size(Msg)) of
			      ok ->
				  ok;
			      {error, enobufs} ->
				  skip({failed_change, sndbuf});
			      {error, Reason2} ->
				  ?FAIL({sndbuf, Reason2})
			  end;
                     true ->
                          ok
                  end,
                  ok = socket:setopt(Sock, otp, rcvbuf, {12, 1024})
          end,
    traffic_ping_pong_send_and_receive_tcp2(InitState#{buf_init => Fun}).

traffic_ping_pong_send_and_receive_tcp2(InitState) ->
    ServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create listen socket",
           cmd  => fun(#{domain := Domain, proto := Proto} = State) ->
                           case socket:open(Domain, stream, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{lsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{domain := local,
                         lsock  := LSock,
                         lsa    := LSA} = _State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, _Port} ->
                                   ok; % We do not care about the port for local
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{lsock := LSock, local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("bound to port: ~w", [Port]),
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "maybe init buffers",
           cmd  => fun(#{lsock := LSock, buf_init := BufInit} = _State) ->
                           BufInit(LSock)
                   end},
         #{desc => "make listen socket",
           cmd  => fun(#{lsock := LSock}) ->
                           socket:listen(LSock)
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain := local,
                         tester := Tester, local_sa := LSA}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, LSA),
                           ok;
                      (#{tester := Tester, local_sa := LSA, lport := Port}) ->
                           ServerSA = LSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (accept)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, accept)
                   end},
         #{desc => "accept",
           cmd  => fun(#{lsock := LSock} = State) ->
                           case socket:accept(LSock) of
                               {ok, Sock} ->
                                   {ok, State#{csock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "create handler",
           cmd  => fun(State) ->
                           Handler = tpp_tcp_handler_create(),
                           ?SEV_IPRINT("handler created: ~p", [Handler]),
                           {ok, State#{handler => Handler}}
                   end},
         #{desc => "monitor handler",
           cmd  => fun(#{handler := Handler} = _State) ->
                           _MRef = erlang:monitor(process, Handler),
                           ok
                   end},
         #{desc => "transfer connection socket ownership to handler",
           cmd  => fun(#{handler := Handler, csock := Sock} = _State) ->
                           socket:setopt(Sock, otp, controlling_process, Handler)
                   end},
         #{desc => "start handler",
           cmd  => fun(#{handler  := Handler,
                         csock    := Sock,
                         send     := Send,
                         recv     := Recv} = _State) ->
                           ?SEV_ANNOUNCE_START(Handler, {Sock, Send, Recv}),
                           ok
                   end},
         #{desc => "await handler ready (init)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = State) ->
                           case ?SEV_AWAIT_READY(Handler, handler, init, 
                                                 [{tester, Tester}]) of
                               ok ->
                                   {ok, maps:remove(csock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv, 
                                               [{handler, Handler}])
                   end},
         #{desc => "order handler to recv",
           cmd  => fun(#{handler := Handler} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Handler, recv),
                           ok
                   end},
         #{desc => "await handler ready (recv)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = State) ->
                           case ?SEV_AWAIT_READY(Handler, handler, recv, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   %% ?SEV_IPRINT("Result: ~p", [Result]),
                                   {ok, State#{result => Result}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv)",
           cmd  => fun(#{tester := Tester, 
                         result := Result} = State) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv, Result),
                           {ok, maps:remove(result, State)}
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "stop handler",
           cmd  => fun(#{handler := Handler}) ->
                           ?SEV_ANNOUNCE_TERMINATE(Handler),
                           ok
                   end},
         #{desc => "await handler termination",
           cmd  => fun(#{handler := Handler} = State) ->
                           ?SEV_AWAIT_TERMINATION(Handler),
                           State1 = maps:remove(handler, State),
                           {ok, State1}
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{domain   := local,
                         lsock    := Sock,
                         local_sa := #{path := Path}} = State) ->
                           (catch socket:close(Sock)),
                           State1 =
                               unlink_path(Path,
                                           fun() -> 
                                                   maps:remove(local_sa, State)
                                           end,
                                           fun() -> State end),
                           {ok, maps:remove(lsock, State1)};
                      (#{lsock := Sock} = State) ->
                           (catch socket:close(Sock)),
                           {ok, maps:remove(lsock, State)}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, ServerSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester, 
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "create node",
           cmd  => fun(#{host := Host} = State) ->
                           case start_node(Host, client) of
                               {ok, Node} ->
                                   ?SEV_IPRINT("(remote) client node ~p started", 
                                               [Node]),
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor client node",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "create remote client",
           cmd  => fun(#{node := Node} = State) ->
                           Pid = tpp_tcp_client_create(Node),
                           ?SEV_IPRINT("remote client created: ~p", [Pid]),
                           {ok, State#{rclient => Pid}}
                   end},
         #{desc => "monitor remote client",
           cmd  => fun(#{rclient := Pid}) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "order remote client to start",
           cmd  => fun(#{rclient   := RClient,
                         proto     := Proto,
                         server_sa := ServerSA,
                         buf_init  := BufInit,
                         send      := Send,
                         recv      := Recv}) ->
                           ?SEV_ANNOUNCE_START(RClient, 
                                               {ServerSA, Proto, BufInit,
                                                Send, Recv}),
                           ok
                   end},
         #{desc => "await remote client ready",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = _State) ->
                           ?SEV_AWAIT_READY(RClient, rclient, init, 
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, connect, 
                                               [{rclient, RClient}]),
                           ok
                   end},
         #{desc => "order remote client to continue (connect)",
           cmd  => fun(#{rclient := RClient}) ->
                           ?SEV_ANNOUNCE_CONTINUE(RClient, connect),
                           ok
                   end},
         #{desc => "await remote client ready (connect)",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = _State) ->
                           ?SEV_AWAIT_READY(RClient, rclient, connect, 
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (connect)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, connect),
                           ok
                   end},
         #{desc => "await continue (send)",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, 
                                               send, 
                                               [{rclient, RClient}])
                   end},
         #{desc => "order remote client to continue (send)",
           cmd  => fun(#{rclient := RClient,
                         msg     := Msg,
                         num     := Num} = State) ->
                           Data = {Msg, Num},
                           ?SEV_ANNOUNCE_CONTINUE(RClient, send, Data),
                           {ok, maps:remove(data, State)}
                   end},
         #{desc => "await remote client ready (send)",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = State) ->
                           case ?SEV_AWAIT_READY(RClient, rclient, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   %% ?SEV_IPRINT("remote client result: "
                                   %%             "~n   ~p", [Result]),
                                   {ok, State#{result => Result}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (send)",
           cmd  => fun(#{tester := Tester, result := Result} = State) ->
                           ?SEV_ANNOUNCE_READY(Tester, send, Result),
                           {ok, maps:remove(result, State)}
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester  := Tester, 
                         rclient := RClient} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester,
                                                     [{rclient, RClient}]) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "stop remote client",
           cmd  => fun(#{rclient := RClient}) ->
                           ?SEV_ANNOUNCE_TERMINATE(RClient),
                           ok
                   end},
         #{desc => "await remote client termination",
           cmd  => fun(#{rclient := RClient} = State) ->
                           ?SEV_AWAIT_TERMINATION(RClient),
                           State1 = maps:remove(rclient, State),
                           {ok, State1}
                   end},
         #{desc => "stop client node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await client node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   {ok, maps:remove(node, State)}
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client    := Pid, 
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, ServerSA),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},
 
         %% The actual test
         #{desc => "order server continue (accept)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, accept),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (connect)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, connect),
                           ok
                   end},
         #{desc => "await server ready (accept)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, accept,
                                            [{client, Client}]),
                           ok
                   end},
         #{desc => "await client ready (connect)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, connect, 
                                            [{server, Server}])
                   end},
         #{desc => "order server continue (recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (send)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send),
                           ok
                   end},
         #{desc => "await client ready (send)",
           cmd  => fun(#{server := Server,
                         client := Client} = State) ->
                           case ?SEV_AWAIT_READY(Client, client, send, 
                                                 [{server, Server}]) of
                               {ok, {_, _, _, _} = Result} ->
                                   ?SEV_IPRINT("client result: "
                                               "~n   ~p", [Result]),
                                   {ok, State#{client_result => Result}};
                               {ok, BadResult} ->
                                   ?SEV_EPRINT("client result: "
                                               "~n   ~p", [BadResult]),
                                   {error, {invalid_client_result, BadResult}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await server ready (recv)",
           cmd  => fun(#{server := Server,
                         client := Client,
                         num    := Num} = State) ->
                           case ?SEV_AWAIT_READY(Server, server, recv,
                                                 [{client, Client}]) of
                               {ok, {Num, _, _, _, _} = Result} ->
                                   ?SEV_IPRINT("server result: "
                                               "~n   ~p", [Result]),
                                   Result2 = erlang:delete_element(1, Result),
                                   {ok, State#{server_result => Result2}};
                               {ok, BadResult} ->
                                   ?SEV_EPRINT("bad server result: "
                                               "~n   ~p", [BadResult]),
                                   {error, {invalid_server_result, BadResult}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "present result",
           cmd  => fun(#{server_result := SRes,
                         client_result := CRes,
                         num           := Num} = State) ->
                           {SSent, SReceived, SStart, SStop} = SRes,
                           {CSent, CReceived, CStart, CStop} = CRes,
                           STime = tdiff(SStart, SStop),
                           CTime = tdiff(CStart, CStop),
                           %% Note that the sizes we are counting is only 
                           %% the "data" part of the messages. There is also
                           %% fixed header for each message, which of cource
                           %% is small for the large messages, but comparatively
                           %% big for the small messages!
                           ?SEV_IPRINT("Results: ~w messages exchanged"
                                       "~n   Server: ~w msec"
                                       "~n      ~.2f msec/message (roundtrip)"
                                       "~n      ~.2f messages/msec (roundtrip)"
                                       "~n      ~w bytes/msec sent"
                                       "~n      ~w bytes/msec received"
                                       "~n   Client: ~w msec"
                                       "~n      ~.2f msec/message (roundtrip)"
                                       "~n      ~.2f messages/msec (roundtrip)"
                                       "~n      ~w bytes/msec sent"
                                       "~n      ~w bytes/msec received",
                                       [Num,
                                        STime,
                                        STime / Num,
                                        Num / STime,
                                        SSent div STime,
                                        SReceived div STime,
                                        CTime,
                                        CTime / Num,
                                        Num / CTime,
                                        CSent div CTime,
                                        CReceived div CTime]),
                           State1 = maps:remove(server_result, State),
                           State2 = maps:remove(client_result, State1),
                           {ok, State2}
                   end},

         %% Terminations
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    ServerInitState = #{domain   => maps:get(domain,   InitState),
                        proto    => maps:get(proto,    InitState),
                        recv     => maps:get(recv,     InitState),
                        send     => maps:get(send,     InitState),
                        buf_init => maps:get(buf_init, InitState)},
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator(s)"),
    ClientInitState = InitState#{host => local_host()},
    Client = ?SEV_START("client", ClientSeq, ClientInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid,
                        num    => maps:get(num, InitState)},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).
    

tpp_tcp_handler_create() ->
    Self = self(),
    erlang:spawn(fun() -> tpp_tcp_handler(Self) end).

tpp_tcp_handler(Parent) ->
    tpp_tcp_handler_init(Parent),
    {Sock, Send, Recv} = tpp_tcp_handler_await_start(Parent),
    tpp_tcp_handler_announce_ready(Parent, init),
    tpp_tcp_handler_await_continue(Parent, recv),
    Result = tpp_tcp_handler_msg_exchange(Sock, Send, Recv),
    tpp_tcp_handler_announce_ready(Parent, recv, Result),
    Reason = tpp_tcp_handler_await_terminate(Parent),
    ?SEV_IPRINT("terminating"),
    exit(Reason).

tpp_tcp_handler_init(Parent) ->
    put(sname, "handler"),
    ?SEV_IPRINT("init"),
    _MRef = erlang:monitor(process, Parent),
    ok.

tpp_tcp_handler_await_start(Parent) ->
    ?SEV_IPRINT("await start"),
    ?SEV_AWAIT_START(Parent).

tpp_tcp_handler_announce_ready(Parent, Slogan) ->
    ?SEV_IPRINT("announce ready (~p)", [Slogan]),
    ?SEV_ANNOUNCE_READY(Parent, Slogan).
tpp_tcp_handler_announce_ready(Parent, Slogan, Extra) ->
    ?SEV_IPRINT("announce ready (~p)", [Slogan]),
    ?SEV_ANNOUNCE_READY(Parent, Slogan, Extra).

tpp_tcp_handler_await_continue(Parent, Slogan) ->
    ?SEV_IPRINT("await continue (~p)", [Slogan]),
    case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of
        ok ->
            %% ?SEV_IPRINT("continue (~p): ok", [Slogan]),
            ok;
        {error, Reason} ->
            ?SEV_EPRINT("continue (~p): error"
                        "~n   ~p", [Slogan, Reason]),
            exit({continue, Slogan, Reason})
    end.

tpp_tcp_handler_await_terminate(Parent) ->
    ?SEV_IPRINT("await terminate"),
    case ?SEV_AWAIT_TERMINATE(Parent, parent) of
        ok ->
            ok;
        {error, Reason} ->
            Reason
    end.

tpp_tcp_handler_msg_exchange(Sock, Send, Recv) ->
    tpp_tcp_handler_msg_exchange_loop(Sock, Send, Recv, 0, 0, 0, undefined).

tpp_tcp_handler_msg_exchange_loop(Sock, Send, Recv, N, Sent, Received, Start) ->
    %% ?SEV_IPRINT("[~w] try receive", [N]),
    case tpp_tcp_recv_req(Sock, Recv) of
        {ok, Msg, RecvSz} ->
            NewStart = if (Start =:= undefined) -> ?LIB:timestamp(); 
                          true -> Start end,
            %% ?SEV_IPRINT("[~w] received - now try send", [N]),
            case tpp_tcp_send_rep(Sock, Send, Msg) of
                {ok, SendSz} ->
                    tpp_tcp_handler_msg_exchange_loop(Sock, Send, Recv,
                                                      N+1,
                                                      Sent+SendSz,
                                                      Received+RecvSz,
                                                      NewStart);
                {error, SReason} ->
                    ?SEV_EPRINT("send (~w): ~p", [N, SReason]),
                    exit({send, SReason, N})
            end;
        {error, closed} ->
            ?SEV_IPRINT("closed - we are done: ~w, ~w, ~w", [N, Sent, Received]),
            Stop = ?LIB:timestamp(),
            {N, Sent, Received, Start, Stop};
        {error, RReason} ->
            ?SEV_EPRINT("recv (~w): ~p", [N, RReason]),
            exit({recv, RReason, N})
    end.
            
%% The (remote) client process

tpp_tcp_client_create(Node) ->
    Self = self(),
    Fun  = fun() -> tpp_tcp_client(Self) end,
    erlang:spawn(Node, Fun).

tpp_tcp_client(Parent) ->
    tpp_tcp_client_init(Parent),
    {ServerSA, Proto, BufInit, Send, Recv} = tpp_tcp_client_await_start(Parent),
    Domain   = maps:get(family, ServerSA),
    Sock     = tpp_tcp_client_sock_open(Domain, Proto, BufInit),
    Path     = tpp_tcp_client_sock_bind(Sock, Domain),
    tpp_tcp_client_announce_ready(Parent, init),
    tpp_tcp_client_await_continue(Parent, connect),
    tpp_tcp_client_sock_connect(Sock, ServerSA),
    tpp_tcp_client_announce_ready(Parent, connect),
    {InitMsg, Num} = tpp_tcp_client_await_continue(Parent, send),
    Result = tpp_tcp_client_msg_exchange(Sock, Send, Recv, InitMsg, Num),
    tpp_tcp_client_announce_ready(Parent, send, Result),
    Reason = tpp_tcp_client_await_terminate(Parent),
    tpp_tcp_client_sock_close(Sock, Path),
    ?SEV_IPRINT("terminating"),
    exit(Reason).

tpp_tcp_client_init(Parent) ->
    put(sname, "rclient"),
    ?SEV_IPRINT("init"),
    _MRef = erlang:monitor(process, Parent),
    ok.

tpp_tcp_client_await_start(Parent) ->
    ?SEV_IPRINT("await start"),
    ?SEV_AWAIT_START(Parent).

tpp_tcp_client_announce_ready(Parent, Slogan) ->
    ?SEV_IPRINT("announce ready (~p)", [Slogan]),
    ?SEV_ANNOUNCE_READY(Parent, Slogan).
tpp_tcp_client_announce_ready(Parent, Slogan, Extra) ->
    ?SEV_IPRINT("announce ready (~p): ~p", [Slogan, Extra]),
    ?SEV_ANNOUNCE_READY(Parent, Slogan, Extra).

tpp_tcp_client_await_continue(Parent, Slogan) ->
    ?SEV_IPRINT("await continue (~p)", [Slogan]),
    case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of
        ok ->
            ?SEV_IPRINT("continue (~p): ok", [Slogan]),
            ok;
        {ok, Data} ->
            ?SEV_IPRINT("continue (~p): ok with data", [Slogan]),
            Data;
        {error, Reason} ->
            ?SEV_EPRINT("continue (~p): error"
                        "~n   ~p", [Slogan, Reason]),
            exit({continue, Slogan, Reason})
    end.

tpp_tcp_client_await_terminate(Parent) ->
    ?SEV_IPRINT("await terminate"),
    case ?SEV_AWAIT_TERMINATE(Parent, parent) of
        ok ->
            ?SEV_IPRINT("termination received: normal"),
            normal;
        {error, Reason} ->
            ?SEV_IPRINT("termination received: ~w", [Reason]),
            Reason
    end.

tpp_tcp_client_msg_exchange(Sock, Send, Recv, InitMsg, Num) ->
    Start = ?LIB:timestamp(),
    tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, InitMsg, 
                                     Num, 0, 0, 0, Start).

tpp_tcp_client_msg_exchange_loop(Sock, _Send, _Recv, _Msg,
                                 Num, Num, Sent, Received,
                                 Start) ->
    Stop = ?LIB:timestamp(),
    case socket:close(Sock) of
        ok ->
            {Sent, Received, Start, Stop};
        {error, Reason} ->
            exit({failed_closing, Reason})
    end;
tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, Data, 
                                 Num, N, Sent, Received, Start) ->
    %% d("tpp_tcp_client_msg_exchange_loop(~w,~w) try send ~w", [Num,N,size(Data)]),
    case tpp_tcp_send_req(Sock, Send, Data) of
        {ok, SendSz} ->
            %% d("tpp_tcp_client_msg_exchange_loop(~w,~w) sent - "
            %%   "now try recv", [Num,N]),
            case tpp_tcp_recv_rep(Sock, Recv) of
                {ok, NewData, RecvSz} ->
                    tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv,
                                                     NewData, Num, N+1,
                                                     Sent+SendSz, 
                                                     Received+RecvSz, 
                                                     Start);
                {error, RReason} ->
                    ?SEV_EPRINT("recv (~w of ~w): ~p: "
                                "~n   ~p", [N, Num, RReason, mq()]),
                    exit({recv, RReason, N})
            end;
        {error, SReason} ->
            ?SEV_EPRINT("send (~w of ~w): ~p"
                        "~n   ~p", [N, Num, SReason, mq()]),
            exit({send, SReason, N})
    end.

tpp_tcp_client_sock_open(Domain, Proto, BufInit) ->
    case socket:open(Domain, stream, Proto) of
        {ok, Sock} ->
            ok = BufInit(Sock),
            Sock;
        {error, Reason} ->
            exit({open_failed, Reason})
    end.

tpp_tcp_client_sock_bind(Sock, Domain) ->
    LSA = which_local_socket_addr(Domain),
    case socket:bind(Sock, LSA) of
        {ok, _} ->
            case socket:sockname(Sock) of
                {ok, #{family := local, path := Path}} ->
                    Path;
                {ok, _} ->
                    undefined;
                {error, Reason1} ->
                    exit({sockname, Reason1})
            end;
        {error, Reason2} ->
            exit({bind, Reason2})
    end.

tpp_tcp_client_sock_connect(Sock, ServerSA) ->
    case socket:connect(Sock, ServerSA) of
        ok ->
            ok;
        {error, Reason} ->
            exit({connect, Reason})
    end.

tpp_tcp_client_sock_close(Sock, Path) ->
    case socket:close(Sock) of
        ok ->
            unlink_path(Path),
            ok;
        {error, Reason} ->
            ?SEV_EPRINT("failed closing: "
                        "~n   Reason: ~p", [Reason]),
            unlink_path(Path),
            {error, {close, Reason}}
    end.

    
    
-define(TPP_REQUEST, 1).
-define(TPP_REPLY,   2).

tpp_tcp_recv_req(Sock, Recv) ->
    tpp_tcp_recv(Sock, Recv, ?TPP_REQUEST).

tpp_tcp_recv_rep(Sock, Recv) ->
    tpp_tcp_recv(Sock, Recv, ?TPP_REPLY).

tpp_tcp_recv(Sock, Recv, Tag) ->
    case Recv(Sock, 0) of
        {ok, <<Tag:32/integer, Sz:32/integer, Data/binary>> = Msg} 
          when (Sz =:= size(Data)) ->
            %% We got it all
            {ok, Data, size(Msg)};
        {ok, <<Tag:32/integer, Sz:32/integer, Data/binary>> = Msg} ->
            Remains = Sz - size(Data),
            tpp_tcp_recv(Sock, Recv, Tag, Remains, size(Msg), [Data]);
        {ok, <<Tag:32/integer, _/binary>>} ->
            {error, {invalid_msg_tag, Tag}};
        {error, _R} = ERROR ->
            ERROR
    end.

tpp_tcp_recv(Sock, Recv, Tag, Remaining, AccSz, Acc) ->
    case Recv(Sock, Remaining) of
        {ok, Data} when (Remaining =:= size(Data)) ->
            %% We got the rest
            TotSz = AccSz + size(Data),
            {ok, erlang:iolist_to_binary(lists:reverse([Data | Acc])), TotSz};
        {ok, Data} when (Remaining > size(Data)) ->
            tpp_tcp_recv(Sock, Recv, Tag, 
                         Remaining - size(Data), AccSz + size(Data),     
                         [Data | Acc]);
        {error, _R} = ERROR ->
            ERROR
    end.
                                                         
            
tpp_tcp_send_req(Sock, Send, Data) ->
    tpp_tcp_send(Sock, Send, ?TPP_REQUEST, Data).

tpp_tcp_send_rep(Sock, Send, Data) ->
    tpp_tcp_send(Sock, Send, ?TPP_REPLY, Data).

tpp_tcp_send(Sock, Send, Tag, Data) ->
    DataSz = size(Data),
    Msg    = <<Tag:32/integer, DataSz:32/integer, Data/binary>>,
    tpp_tcp_send_msg(Sock, Send, Msg, 0).

tpp_tcp_send_msg(Sock, Send, Msg, AccSz) when is_binary(Msg) ->
    case Send(Sock, Msg) of
        ok ->
            {ok, AccSz+size(Msg)};
        {ok, Rest} -> % This is an IOVec
            RestBin = list_to_binary(Rest),
            tpp_tcp_send_msg(Sock, Send, RestBin, AccSz+(size(Msg)-size(RestBin)));
        {error, _} = ERROR ->
            ERROR
    end.
    

%% size_of_data(Data) when is_binary(Data) ->
%%     size(Data);
%% size_of_data(Data) when is_list(Data) ->
%%     size_of_iovec(Data, 0).

%% size_of_iovec([], Sz) ->
%%     Sz;
%% size_of_iovec([B|IOVec], Sz) ->
%%     size_of_iovec(IOVec, Sz+size(B)).

mq() ->
    mq(self()).

mq(Pid) when is_pid(Pid) ->
    Tag = messages,
    {Tag, Msgs} = process_info(Pid, Tag),
    Msgs.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Ping-Pong for UDP

traffic_ping_pong_sendto_and_recvfrom_udp(InitState) ->
    Send = fun(Sock, Data, Dest) ->
                   socket:sendto(Sock, Data, Dest)
           end,
    Recv = fun(Sock, Sz)         ->
                   socket:recvfrom(Sock, Sz)
           end,
    InitState2 = InitState#{send => Send, % Send function
                            recv => Recv  % Receive function
                           },
    traffic_ping_pong_send_and_receive_udp(InitState2).

traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) ->
    Send = fun(Sock, Data, Dest) when is_binary(Data) ->
                   MsgHdr = #{addr => Dest, iov => [Data]},
                   socket:sendmsg(Sock, MsgHdr);
              (Sock, Data, Dest) when is_list(Data) -> %% We assume iovec...
                   MsgHdr = #{addr => Dest, iov => Data},
                   socket:sendmsg(Sock, MsgHdr)
           end,
    Recv = fun(Sock, Sz)   ->
                   case socket:recvmsg(Sock, Sz, 0) of
                       {ok, #{addr  := Source,
                              iov   := [Data]}} ->
                           {ok, {Source, Data}};
                       {error, _} = ERROR ->
                           ERROR
                   end
           end,
    InitState2 = InitState#{send => Send, % Send function
                            recv => Recv  % Receive function
                           },
    traffic_ping_pong_send_and_receive_udp(InitState2).


traffic_ping_pong_send_and_receive_udp(#{msg := Msg} = InitState) ->
    Fun = fun(Sock) -> 
                  {ok, RcvSz} = socket:getopt(Sock, socket, rcvbuf),
                  if (RcvSz =< (8+size(Msg))) ->
                          i("adjust socket rcvbuf buffer size"),
                          ok = socket:setopt(Sock, socket, rcvbuf, 1024+size(Msg));
                     true ->
                          ok
                  end,
                  {ok, SndSz} = socket:getopt(Sock, socket, sndbuf),
                  if (SndSz =< (8+size(Msg))) ->
                          i("adjust socket sndbuf buffer size"),
                          ok = socket:setopt(Sock, socket, sndbuf, 1024+size(Msg));
                     true ->
                          ok
                  end,
                  {ok, OtpRcvBuf} = socket:getopt(Sock, otp, rcvbuf),
                  if
                      (OtpRcvBuf =< (8+size(Msg))) ->
                          i("adjust otp rcvbuf buffer size"),
                          ok = socket:setopt(Sock, otp, rcvbuf, 1024+size(Msg));
                      true ->
                          ok
                  end
          end,
    traffic_ping_pong_send_and_receive_udp2(InitState#{buf_init => Fun}).

traffic_ping_pong_send_and_receive_udp2(InitState) ->
    ServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           LSA = which_local_socket_addr(Domain),
                           {ok, State#{local_sa => LSA}}
                   end},
         #{desc => "create socket",
           cmd  => fun(#{domain := Domain, proto := Proto} = State) ->
                           case socket:open(Domain, dgram, Proto) of
                               {ok, Sock} ->
                                   {ok, State#{sock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "bind to local address",
           cmd  => fun(#{domain := local,
                         sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{sock := Sock, local_sa := LSA} = State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{port => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "maybe init buffers",
           cmd  => fun(#{sock := Sock, buf_init := BufInit} = _State) ->
                           BufInit(Sock)
                   end},
         #{desc => "create handler",
           cmd  => fun(State) ->
                           Handler = tpp_udp_server_handler_create(),
                           ?SEV_IPRINT("handler created: ~p", [Handler]),
                           {ok, State#{handler => Handler}}
                   end},
         #{desc => "monitor handler",
           cmd  => fun(#{handler := Handler} = _State) ->
                           _MRef = erlang:monitor(process, Handler),
                           ok
                   end},
         #{desc => "start handler",
           cmd  => fun(#{handler := Handler,
                         sock    := Sock,
                         send    := Send,
                         recv    := Recv} = _State) ->
                           ?SEV_ANNOUNCE_START(Handler, {Sock, Send, Recv}),
                           ok
                   end},
         #{desc => "await handler ready (init)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = State) ->
                           case ?SEV_AWAIT_READY(Handler, handler, init, 
                                                 [{tester, Tester}]) of
                               ok ->
                                   {ok, maps:remove(csock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain := local,
                         tester := Tester, local_sa := LSA}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, LSA),
                           ok;
                      (#{tester := Tester, local_sa := LSA, port := Port}) ->
                           ServerSA = LSA#{port => Port},
                           ?SEV_ANNOUNCE_READY(Tester, init, ServerSA),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (recv)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv, 
                                               [{handler, Handler}])
                   end},
         #{desc => "order handler to recv",
           cmd  => fun(#{handler := Handler,
                         sock    := _Sock} = _State) ->
                           %% socket:setopt(Sock, otp, debug, true),
                           ?SEV_ANNOUNCE_CONTINUE(Handler, recv),
                           ok
                   end},
         #{desc => "await continue (close)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, close, 
                                               [{handler, Handler}])
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           %% socket:setopt(Sock, otp, debug, true),
                           case socket:close(Sock) of
                               ok ->
                                   {ok, maps:remove(sock, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "(maybe) unlink socket",
           cmd  => fun(#{domain   := local,
                         local_sa := #{path := Path}} = State) ->
                           unlink_path(Path,
                                       fun() ->
                                               {ok, maps:remove(local_sa, State)}
                                       end,
                                       fun() ->
                                               ok
                                       end);
                      (_) ->
                           ok
                   end},
         #{desc => "announce ready (close)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_ANNOUNCE_READY(Tester, close),
                           ok
                   end},
         #{desc => "await handler ready (recv)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = State) ->
                           case ?SEV_AWAIT_READY(Handler, handler, recv, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   %% ?SEV_IPRINT("Result: ~p", [Result]),
                                   {ok, State#{result => Result}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (recv)",
           cmd  => fun(#{tester := Tester, 
                         result := Result} = State) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv, Result),
                           {ok, maps:remove(result, State)}
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "stop handler",
           cmd  => fun(#{handler := Handler}) ->
                           ?SEV_ANNOUNCE_TERMINATE(Handler),
                           ok
                   end},
         #{desc => "await handler termination",
           cmd  => fun(#{handler := Handler} = State) ->
                           ?SEV_AWAIT_TERMINATION(Handler),
                           State1 = maps:remove(handler, State),
                           {ok, State1}
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           {Tester, ServerSA} = ?SEV_AWAIT_START(),
                           {ok, State#{tester    => Tester, 
                                       server_sa => ServerSA}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** Init part ***
         #{desc => "create node",
           cmd  => fun(#{host := Host} = State) ->
                           case start_node(Host, client) of
                               {ok, Node} ->
                                   ?SEV_IPRINT("(remote) client node ~p started", 
                                               [Node]),
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor client node",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "create (remote) handler",
           cmd  => fun(#{node := Node} = State) ->
                           Pid = tpp_udp_client_handler_create(Node),
                           ?SEV_IPRINT("handler created: ~p", [Pid]),
                           {ok, State#{handler => Pid}}
                   end},
         #{desc => "monitor remote handler",
           cmd  => fun(#{handler := Pid}) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "order remote handler to start",
           cmd  => fun(#{handler   := Handler,
                         server_sa := ServerSA,
                         proto     := Proto,
                         buf_init  := BufInit,
                         send      := Send,
                         recv      := Recv}) ->
                           ?SEV_ANNOUNCE_START(Handler, 
                                               {ServerSA, Proto, BufInit,
                                                Send, Recv}),
                           ok
                   end},
         #{desc => "await (remote) handler ready",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = _State) ->
                           ?SEV_AWAIT_READY(Handler, handler, init, 
                                            [{tester, Tester}])
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (send)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, 
                                               send, 
                                               [{handler, Handler}])
                   end},
         #{desc => "order handler to continue (send)",
           cmd  => fun(#{handler := Handler,
                         msg     := Msg,
                         num     := Num} = State) ->
                           Data = {Msg, Num},
                           ?SEV_ANNOUNCE_CONTINUE(Handler, send, Data),
                           {ok, maps:remove(data, State)}
                   end},
         #{desc => "await remote handler ready (send)",
           cmd  => fun(#{tester  := Tester,
                         handler := Handler} = State) ->
                           case ?SEV_AWAIT_READY(Handler, handler, send, 
                                                 [{tester, Tester}]) of
                               {ok, Result} ->
                                   %% ?SEV_IPRINT("remote client result: "
                                   %%             "~n   ~p", [Result]),
                                   {ok, State#{result => Result}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (send)",
           cmd  => fun(#{tester := Tester, result := Result} = State) ->
                           ?SEV_ANNOUNCE_READY(Tester, send, Result),
                           {ok, maps:remove(result, State)}
                   end},

         %% Termination
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester  := Tester, 
                         handler := Handler} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester,
                                                     [{handler, Handler}]) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "stop (remote) handler",
           cmd  => fun(#{handler := Handler}) ->
                           ?SEV_ANNOUNCE_TERMINATE(Handler),
                           ok
                   end},
         #{desc => "await (remote) handler termination",
           cmd  => fun(#{handler := Handler} = State) ->
                           ?SEV_AWAIT_TERMINATION(Handler),
                           State1 = maps:remove(handler, State),
                           {ok, State1}
                   end},
         #{desc => "stop client node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await client node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   {ok, maps:remove(node, State)}
                           end
                   end},

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{server := Pid} = State) ->
                           {ok, ServerSA} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_sa => ServerSA}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{client    := Pid, 
                         server_sa := ServerSA} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, ServerSA),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, client, init)
                   end},
 
         %% The actual test
         #{desc => "order server continue (recv)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, recv),
                           ok
                   end},
         ?SEV_SLEEP(?SECS(1)),
         #{desc => "order client continue (send)",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, send),
                           ok
                   end},
         #{desc => "await client ready (send)",
           cmd  => fun(#{server := Server,
                         client := Client} = State) ->
                           case ?SEV_AWAIT_READY(Client, client, send, 
                                                 [{server, Server}]) of
                               {ok, {_, _, _, _} = Result} ->
                                   ?SEV_IPRINT("client result: "
                                               "~n   ~p", [Result]),
                                   {ok, State#{client_result => Result}};
                               {ok, BadResult} ->
                                   ?SEV_EPRINT("client result: "
                                               "~n   ~p", [BadResult]),
                                   {error, {invalid_client_result, BadResult}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server continue (close)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Pid, close),
                           ok
                   end},
         #{desc => "await server ready (close)",
           cmd  => fun(#{server := Pid} = _State) ->
                           ok = ?SEV_AWAIT_READY(Pid, server, close)
                   end},
         %% Because of the way we control the server, there is no real 
         %% point in collecting statistics from it (the time will include
         %% our communication with it).
         #{desc => "await server ready (recv)",
           cmd  => fun(#{server := Server,
                         client := Client} = _State) ->
                           case ?SEV_AWAIT_READY(Server, server, recv,
                                                 [{client, Client}]) of
                               {ok, _Result} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "present result",
           cmd  => fun(#{client_result := CRes,
                         num           := Num} = State) ->
                           {CSent, CReceived, CStart, CStop} = CRes,
                           CTime = tdiff(CStart, CStop),
                           %% Note that the sizes we are counting is only 
                           %% the "data" part of the messages. There is also
                           %% fixed header for each message, which of cource
                           %% is small for the large messages, but comparatively
                           %% big for the small messages!
                           ?SEV_IPRINT("Results: ~w messages exchanged"
                                       "~n   Client: ~w msec"
                                       "~n      ~.2f msec/message (roundtrip)"
                                       "~n      ~.2f messages/msec (roundtrip)"
                                       "~n      ~w bytes/msec sent"
                                       "~n      ~w bytes/msec received",
                                       [Num,
                                        CTime,
                                        CTime / Num,
                                        Num / CTime,
                                        CSent div CTime,
                                        CReceived div CTime]),
                           State1 = maps:remove(client_result, State),
                           {ok, State1}
                   end},

         %% Terminations
         #{desc => "order client to terminate",
           cmd  => fun(#{client := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await client termination",
           cmd  => fun(#{client := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(client, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "order server to terminate",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Pid),
                           ok
                   end},
         #{desc => "await server termination",
           cmd  => fun(#{server := Pid} = State) ->
                           case ?SEV_AWAIT_TERMINATION(Pid) of
                               ok ->
                                   State1 = maps:remove(server, State),
                                   {ok, State1};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],


    i("start server evaluator"),
    ServerInitState = #{domain   => maps:get(domain,   InitState),
                        proto    => maps:get(proto,    InitState),
                        recv     => maps:get(recv,     InitState),
                        send     => maps:get(send,     InitState),
                        buf_init => maps:get(buf_init, InitState)},
    Server = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator(s)"),
    ClientInitState = InitState#{host => local_host()},
    Client = ?SEV_START("client", ClientSeq, ClientInitState),

    i("start 'tester' evaluator"),
    TesterInitState = #{server => Server#ev.pid,
                        client => Client#ev.pid,
                        num    => maps:get(num, InitState)},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).



%% Server side handler process
%% We don't actually need a separate process for this socket, 
%% but we do it anyway to simplify the sequence.
tpp_udp_server_handler_create() ->
    Self = self(),
    erlang:spawn(fun() -> tpp_udp_server_handler(Self) end).

tpp_udp_server_handler(Parent) ->
    tpp_udp_server_handler_init(Parent),
    {Sock, Send, Recv} = tpp_udp_handler_await_start(Parent),
    tpp_udp_handler_announce_ready(Parent, init),
    tpp_udp_handler_await_continue(Parent, recv),
    Result = tpp_udp_server_handler_msg_exchange(Sock, Send, Recv),
    tpp_udp_handler_announce_ready(Parent, recv, Result),
    Reason = tpp_udp_handler_await_terminate(Parent),
    ?SEV_IPRINT("terminating"),
    exit(Reason).

tpp_udp_server_handler_init(Parent) ->
    put(sname, "shandler"),
    ?SEV_IPRINT("init"),
    _MRef = erlang:monitor(process, Parent),
    ok.

tpp_udp_server_handler_msg_exchange(Sock, Send, Recv) ->
    tpp_udp_server_handler_msg_exchange_loop(Sock, Send, Recv,
                                             0, 0, 0, undefined).

tpp_udp_server_handler_msg_exchange_loop(Sock, Send, Recv, 
                                         N, Sent, Received, Start) ->
    %% ?SEV_IPRINT("[~w] try receive", [N]),
    %% if 
    %%     (N =:= (?TPP_SMALL_NUM-2)) -> 
    %%         ?SEV_IPRINT("[~w] try receive", [N]),
    %%         socket:setopt(Sock, otp, debug, true); 
    %%     true -> ok
    %% end,
    try tpp_udp_recv_req(Sock, Recv) of
        {ok, Msg, RecvSz, From} ->
            NewStart = if (Start =:= undefined) -> ?LIB:timestamp(); 
                          true -> Start end,
            %% ?SEV_IPRINT("[~w] received - now try send", [N]),
            try tpp_udp_send_rep(Sock, Send, Msg, From) of
                {ok, SendSz} ->
                    tpp_udp_server_handler_msg_exchange_loop(Sock, Send, Recv,
                                                             N+1,
                                                             Sent+SendSz,
                                                             Received+RecvSz,
                                                             NewStart);
                {error, SReason} ->
                    ?SEV_EPRINT("send (~w): ~p", [N, SReason]),
                    exit({send, SReason, N})
	    catch
		SC:SE:SS ->
		    exit({send, {SC, SE, SS}, N})
            end;
        {error, closed} ->
            ?SEV_IPRINT("closed - we are done: ~w, ~w, ~w",
                        [N, Sent, Received]),
            Stop = ?LIB:timestamp(),
            {N, Sent, Received, Start, Stop};
        {error, RReason} ->
            ?SEV_EPRINT("recv (~w): ~p", [N, RReason]),
            exit({recv, RReason, N})
    catch
	RC:RE:RS ->
	    exit({recv, {RC, RE, RS}, N})	
    end.
  

%% The (remote) client side handler process

tpp_udp_client_handler_create(Node) ->
    Self = self(),
    Fun  = fun() -> put(sname, "chandler"), tpp_udp_client_handler(Self) end,
    erlang:spawn(Node, Fun).

tpp_udp_client_handler(Parent) ->
    tpp_udp_client_handler_init(Parent),
    ?SEV_IPRINT("await start command"),
    {ServerSA, Proto, BufInit, Send, Recv} = tpp_udp_handler_await_start(Parent),
    ?SEV_IPRINT("start command with"
                "~n   ServerSA: ~p", [ServerSA]),
    Domain   = maps:get(family, ServerSA),
    Sock     = tpp_udp_sock_open(Domain, Proto, BufInit),
    Path     = tpp_udp_sock_bind(Sock, Domain),
    ?SEV_IPRINT("announce ready", []),
    tpp_udp_handler_announce_ready(Parent, init),
    {InitMsg, Num} = tpp_udp_handler_await_continue(Parent, send),
    ?SEV_IPRINT("received continue with"
                "~n   Num: ~p", [Num]),
    Result = tpp_udp_client_handler_msg_exchange(Sock, ServerSA, 
                                                 Send, Recv, InitMsg, Num),
    ?SEV_IPRINT("ready"),
    tpp_udp_handler_announce_ready(Parent, send, Result),
    ?SEV_IPRINT("await terminate"),
    Reason = tpp_udp_handler_await_terminate(Parent),
    ?SEV_IPRINT("terminate with ~p", [Reason]),
    tpp_udp_sock_close(Sock, Path),
    ?SEV_IPRINT("terminating"),
    exit(Reason).

tpp_udp_client_handler_init(Parent) ->
    put(sname, "chandler"),
    ?SEV_IPRINT("init"),
    _MRef = erlang:monitor(process, Parent),
    ok.

tpp_udp_client_handler_msg_exchange(Sock, ServerSA,
                                    Send, Recv, InitMsg, Num) ->
    Start = ?LIB:timestamp(),
    tpp_udp_client_handler_msg_exchange_loop(Sock, ServerSA,
                                             Send, Recv, InitMsg,
                                             Num, 0, 0, 0, Start).

tpp_udp_client_handler_msg_exchange_loop(_Sock, _Dest, _Send, _Recv, _Msg,
                                         Num, Num, Sent, Received,
                                         Start) ->
    Stop = ?LIB:timestamp(),
    {Sent, Received, Start, Stop};
tpp_udp_client_handler_msg_exchange_loop(Sock, Dest, Send, Recv, Data,
                                         Num, N, Sent, Received, Start) ->
    case tpp_udp_send_req(Sock, Send, Data, Dest) of
        {ok, SendSz} ->
            case tpp_udp_recv_rep(Sock, Recv) of
                {ok, NewData, RecvSz, Dest} ->
                    tpp_udp_client_handler_msg_exchange_loop(Sock, Dest,
                                                             Send, Recv,
                                                             NewData, Num, N+1,
                                                             Sent+SendSz, 
                                                             Received+RecvSz, 
                                                             Start);
                {error, RReason} ->
                    ?SEV_EPRINT("recv (~w of ~w): ~p", [N, Num, RReason]),
                    exit({recv, RReason, N})
            end;
        {error, SReason} ->
            ?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]),
            exit({send, SReason, N})
    end.


tpp_udp_recv_req(Sock, Recv) ->
    tpp_udp_recv(Sock, Recv, ?TPP_REQUEST).

tpp_udp_recv_rep(Sock, Recv) ->
    tpp_udp_recv(Sock, Recv, ?TPP_REPLY).

tpp_udp_recv(Sock, Recv, Tag) ->
    %% ok = socket:setopt(Sock, otp, debug, true),
    try Recv(Sock, 0) of
        {ok, {Source, <<Tag:32/integer, Sz:32/integer, Data/binary>> = Msg}} 
          when (Sz =:= size(Data)) ->
	    %% ok = socket:setopt(Sock, otp, debug, false),
            %% We got it all
            %% ?SEV_IPRINT("tpp_udp_recv -> got all: "
            %%             "~n   Source:     ~p"
            %%             "~n   Tag:        ~p"
            %%             "~n   Sz:         ~p"
            %%             "~n   size(Data): ~p",
            %%             [Source, Tag, Sz, size(Data)]),
            {ok, Data, size(Msg), Source};
        {ok, {_Source, <<Tag:32/integer, Sz:32/integer, Data/binary>>}} ->
	    %% ok = socket:setopt(Sock, otp, debug, false),
            {error, {invalid_msg, Sz, size(Data)}};
        {ok, {_, <<Tag:32/integer, _/binary>>}} ->
	    %% ok = socket:setopt(Sock, otp, debug, false),
            {error, {invalid_msg_tag, Tag}};
        {error, _} = ERROR ->
	    %% ok = socket:setopt(Sock, otp, debug, false),
            ERROR
    catch
	C:E:S ->
	    {error, {catched, C, E, S}}
    end.

tpp_udp_send_req(Sock, Send, Data, Dest) ->
    tpp_udp_send(Sock, Send, ?TPP_REQUEST, Data, Dest).

tpp_udp_send_rep(Sock, Send, Data, Dest) ->
    tpp_udp_send(Sock, Send, ?TPP_REPLY, Data, Dest).

tpp_udp_send(Sock, Send, Tag, Data, Dest) ->
    DataSz = size(Data),
    Msg    = <<Tag:32/integer, DataSz:32/integer, Data/binary>>,
    tpp_udp_send_msg(Sock, Send, Msg, Dest, 0).

tpp_udp_send_msg(Sock, Send, Msg, Dest, AccSz) when is_binary(Msg) ->
    case Send(Sock, Msg, Dest) of
        ok ->
            {ok, AccSz+size(Msg)};
        {ok, Rest} -> % This is an IOVec
            RestBin = list_to_binary(Rest),
            tpp_udp_send_msg(Sock, Send, RestBin, Dest,
                             AccSz+(size(Msg)-size(RestBin)));
        {error, _} = ERROR ->
            ERROR
    end.
    

tpp_udp_handler_await_start(Parent) ->
    ?SEV_IPRINT("await start"),
    ?SEV_AWAIT_START(Parent).

tpp_udp_handler_announce_ready(Parent, Slogan) ->
    ?SEV_IPRINT("announce ready (~p)", [Slogan]),
    ?SEV_ANNOUNCE_READY(Parent, Slogan).
tpp_udp_handler_announce_ready(Parent, Slogan, Extra) ->
    ?SEV_IPRINT("announce ready (~p)", [Slogan]),
    ?SEV_ANNOUNCE_READY(Parent, Slogan, Extra).

tpp_udp_handler_await_continue(Parent, Slogan) ->
    ?SEV_IPRINT("await continue (~p)", [Slogan]),
    case ?SEV_AWAIT_CONTINUE(Parent, parent, Slogan) of
        ok ->
            ?SEV_IPRINT("continue (~p): ok", [Slogan]),
            ok;
        {ok, Data} ->
            ?SEV_IPRINT("continue (~p): ok with data", [Slogan]),
            Data;
        {error, Reason} ->
            ?SEV_EPRINT("continue (~p): error"
                        "~n   ~p", [Slogan, Reason]),
            exit({continue, Slogan, Reason})
    end.

tpp_udp_handler_await_terminate(Parent) ->
    ?SEV_IPRINT("await terminate"),
    case ?SEV_AWAIT_TERMINATE(Parent, parent) of
        ok ->
            ok;
        {error, Reason} ->
            Reason
    end.


tpp_udp_sock_open(Domain, Proto, BufInit) ->
    case socket:open(Domain, dgram, Proto) of
        {ok, Sock} ->
            ok = BufInit(Sock),
            Sock;
        {error, Reason} ->
            exit({open_failed, Reason})
    end.

tpp_udp_sock_bind(Sock, Domain) ->
    LSA = which_local_socket_addr(Domain),
    case socket:bind(Sock, LSA) of
        {ok, _} ->
            ok;
        {error, Reason} ->
            exit({bind, Reason})
    end.

tpp_udp_sock_close(Sock, Path) ->
    case socket:close(Sock) of
        ok ->
            unlink_path(Path),
            ok;
        {error, Reason} ->
            ?SEV_EPRINT("Failed closing socket: "
                        "~n   ~p", [Reason]),
            unlink_path(Path),
            {error, {close, Reason}}
    end.



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgenf_cgenf_small_tcp4(suite) ->
    [];
ttest_sgenf_cgenf_small_tcp4(doc) ->
    [];
ttest_sgenf_cgenf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgenf_small_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgenf_cgenf_small_tcp6(suite) ->
    [];
ttest_sgenf_cgenf_small_tcp6(doc) ->
    [];
ttest_sgenf_cgenf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgenf_small_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgenf_cgenf_medium_tcp4(suite) ->
    [];
ttest_sgenf_cgenf_medium_tcp4(doc) ->
    [];
ttest_sgenf_cgenf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgenf_medium_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgenf_cgenf_medium_tcp6(suite) ->
    [];
ttest_sgenf_cgenf_medium_tcp6(doc) ->
    [];
ttest_sgenf_cgenf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgenf_medium_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgenf_cgenf_large_tcp4(suite) ->
    [];
ttest_sgenf_cgenf_large_tcp4(doc) ->
    [];
ttest_sgenf_cgenf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgenf_large_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgenf_cgenf_large_tcp6(suite) ->
    [];
ttest_sgenf_cgenf_large_tcp6(doc) ->
    [];
ttest_sgenf_cgenf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgenf_large_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgenf_cgeno_small_tcp4(suite) ->
    [];
ttest_sgenf_cgeno_small_tcp4(doc) ->
    [];
ttest_sgenf_cgeno_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgeno_small_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgenf_cgeno_small_tcp6(suite) ->
    [];
ttest_sgenf_cgeno_small_tcp6(doc) ->
    [];
ttest_sgenf_cgeno_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgeno_small_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgenf_cgeno_medium_tcp4(suite) ->
    [];
ttest_sgenf_cgeno_medium_tcp4(doc) ->
    [];
ttest_sgenf_cgeno_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgeno_medium_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgenf_cgeno_medium_tcp6(suite) ->
    [];
ttest_sgenf_cgeno_medium_tcp6(doc) ->
    [];
ttest_sgenf_cgeno_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgeno_medium_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgenf_cgeno_large_tcp4(suite) ->
    [];
ttest_sgenf_cgeno_large_tcp4(doc) ->
    [];
ttest_sgenf_cgeno_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgeno_large_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgenf_cgeno_large_tcp6(suite) ->
    [];
ttest_sgenf_cgeno_large_tcp6(doc) ->
    [];
ttest_sgenf_cgeno_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgeno_large_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgenf_cgent_small_tcp4(suite) ->
    [];
ttest_sgenf_cgent_small_tcp4(doc) ->
    [];
ttest_sgenf_cgent_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgent_small_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgenf_cgent_small_tcp6(suite) ->
    [];
ttest_sgenf_cgent_small_tcp6(doc) ->
    [];
ttest_sgenf_cgent_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgeno_small_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgenf_cgent_medium_tcp4(suite) ->
    [];
ttest_sgenf_cgent_medium_tcp4(doc) ->
    [];
ttest_sgenf_cgent_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgent_medium_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgenf_cgent_medium_tcp6(suite) ->
    [];
ttest_sgenf_cgent_medium_tcp6(doc) ->
    [];
ttest_sgenf_cgent_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgent_medium_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgenf_cgent_large_tcp4(suite) ->
    [];
ttest_sgenf_cgent_large_tcp4(doc) ->
    [];
ttest_sgenf_cgent_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgent_large_tcp4,
              Runtime,
              inet,
              gen, false,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgenf_cgent_large_tcp6(suite) ->
    [];
ttest_sgenf_cgent_large_tcp6(doc) ->
    [];
ttest_sgenf_cgent_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_cgent_large_tcp6,
              Runtime,
              inet6,
              gen, false,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgenf_csockf_small_tcp4(suite) ->
    [];
ttest_sgenf_csockf_small_tcp4(doc) ->
    [];
ttest_sgenf_csockf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockf_small_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgenf_csockf_small_tcp6(suite) ->
    [];
ttest_sgenf_csockf_small_tcp6(doc) ->
    [];
ttest_sgenf_csockf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockf_small_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgenf_csockf_medium_tcp4(suite) ->
    [];
ttest_sgenf_csockf_medium_tcp4(doc) ->
    [];
ttest_sgenf_csockf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockf_medium_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgenf_csockf_medium_tcp6(suite) ->
    [];
ttest_sgenf_csockf_medium_tcp6(doc) ->
    [];
ttest_sgenf_csockf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockf_medium_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgenf_csockf_large_tcp4(suite) ->
    [];
ttest_sgenf_csockf_large_tcp4(doc) ->
    [];
ttest_sgenf_csockf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockf_large_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgenf_csockf_large_tcp6(suite) ->
    [];
ttest_sgenf_csockf_large_tcp6(doc) ->
    [];
ttest_sgenf_csockf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockf_large_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgenf_csocko_small_tcp4(suite) ->
    [];
ttest_sgenf_csocko_small_tcp4(doc) ->
    [];
ttest_sgenf_csocko_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csocko_small_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgenf_csocko_small_tcp6(suite) ->
    [];
ttest_sgenf_csocko_small_tcp6(doc) ->
    [];
ttest_sgenf_csocko_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csocko_small_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgenf_csocko_medium_tcp4(suite) ->
    [];
ttest_sgenf_csocko_medium_tcp4(doc) ->
    [];
ttest_sgenf_csocko_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csocko_medium_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgenf_csocko_medium_tcp6(suite) ->
    [];
ttest_sgenf_csocko_medium_tcp6(doc) ->
    [];
ttest_sgenf_csocko_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csocko_medium_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgenf_csocko_large_tcp4(suite) ->
    [];
ttest_sgenf_csocko_large_tcp4(doc) ->
    [];
ttest_sgenf_csocko_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csocko_large_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgenf_csocko_large_tcp6(suite) ->
    [];
ttest_sgenf_csocko_large_tcp6(doc) ->
    [];
ttest_sgenf_csocko_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csocko_large_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgenf_csockt_small_tcp4(suite) ->
    [];
ttest_sgenf_csockt_small_tcp4(doc) ->
    [];
ttest_sgenf_csockt_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockt_small_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgenf_csockt_small_tcp6(suite) ->
    [];
ttest_sgenf_csockt_small_tcp6(doc) ->
    [];
ttest_sgenf_csockt_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csocko_small_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgenf_csockt_medium_tcp4(suite) ->
    [];
ttest_sgenf_csockt_medium_tcp4(doc) ->
    [];
ttest_sgenf_csockt_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockt_medium_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgenf_csockt_medium_tcp6(suite) ->
    [];
ttest_sgenf_csockt_medium_tcp6(doc) ->
    [];
ttest_sgenf_csockt_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockt_medium_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgenf_csockt_large_tcp4(suite) ->
    [];
ttest_sgenf_csockt_large_tcp4(doc) ->
    [];
ttest_sgenf_csockt_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockt_large_tcp4,
              Runtime,
              inet,
              gen, false,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgenf_csockt_large_tcp6(suite) ->
    [];
ttest_sgenf_csockt_large_tcp6(doc) ->
    [];
ttest_sgenf_csockt_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgenf_csockt_large_tcp6,
              Runtime,
              inet6,
              gen, false,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgeno_cgenf_small_tcp4(suite) ->
    [];
ttest_sgeno_cgenf_small_tcp4(doc) ->
    [];
ttest_sgeno_cgenf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgenf_small_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgeno_cgenf_small_tcp6(suite) ->
    [];
ttest_sgeno_cgenf_small_tcp6(doc) ->
    [];
ttest_sgeno_cgenf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgenf_small_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgeno_cgenf_medium_tcp4(suite) ->
    [];
ttest_sgeno_cgenf_medium_tcp4(doc) ->
    [];
ttest_sgeno_cgenf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgenf_medium_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgeno_cgenf_medium_tcp6(suite) ->
    [];
ttest_sgeno_cgenf_medium_tcp6(doc) ->
    [];
ttest_sgeno_cgenf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgenf_medium_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgeno_cgenf_large_tcp4(suite) ->
    [];
ttest_sgeno_cgenf_large_tcp4(doc) ->
    [];
ttest_sgeno_cgenf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgenf_large_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgeno_cgenf_large_tcp6(suite) ->
    [];
ttest_sgeno_cgenf_large_tcp6(doc) ->
    [];
ttest_sgeno_cgenf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgenf_large_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgeno_cgeno_small_tcp4(suite) ->
    [];
ttest_sgeno_cgeno_small_tcp4(doc) ->
    [];
ttest_sgeno_cgeno_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgeno_small_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgeno_cgeno_small_tcp6(suite) ->
    [];
ttest_sgeno_cgeno_small_tcp6(doc) ->
    [];
ttest_sgeno_cgeno_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgeno_small_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgeno_cgeno_medium_tcp4(suite) ->
    [];
ttest_sgeno_cgeno_medium_tcp4(doc) ->
    [];
ttest_sgeno_cgeno_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgeno_medium_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgeno_cgeno_medium_tcp6(suite) ->
    [];
ttest_sgeno_cgeno_medium_tcp6(doc) ->
    [];
ttest_sgeno_cgeno_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgeno_medium_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgeno_cgeno_large_tcp4(suite) ->
    [];
ttest_sgeno_cgeno_large_tcp4(doc) ->
    [];
ttest_sgeno_cgeno_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgeno_large_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgeno_cgeno_large_tcp6(suite) ->
    [];
ttest_sgeno_cgeno_large_tcp6(doc) ->
    [];
ttest_sgeno_cgeno_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgeno_large_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgeno_cgent_small_tcp4(suite) ->
    [];
ttest_sgeno_cgent_small_tcp4(doc) ->
    [];
ttest_sgeno_cgent_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgent_small_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgeno_cgent_small_tcp6(suite) ->
    [];
ttest_sgeno_cgent_small_tcp6(doc) ->
    [];
ttest_sgeno_cgent_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgeno_small_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgeno_cgent_medium_tcp4(suite) ->
    [];
ttest_sgeno_cgent_medium_tcp4(doc) ->
    [];
ttest_sgeno_cgent_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgent_medium_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgeno_cgent_medium_tcp6(suite) ->
    [];
ttest_sgeno_cgent_medium_tcp6(doc) ->
    [];
ttest_sgeno_cgent_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgent_medium_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgeno_cgent_large_tcp4(suite) ->
    [];
ttest_sgeno_cgent_large_tcp4(doc) ->
    [];
ttest_sgeno_cgent_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgent_large_tcp4,
              Runtime,
              inet,
              gen, once,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgeno_cgent_large_tcp6(suite) ->
    [];
ttest_sgeno_cgent_large_tcp6(doc) ->
    [];
ttest_sgeno_cgent_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_cgent_large_tcp6,
              Runtime,
              inet6,
              gen, once,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgeno_csockf_small_tcp4(suite) ->
    [];
ttest_sgeno_csockf_small_tcp4(doc) ->
    [];
ttest_sgeno_csockf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockf_small_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgeno_csockf_small_tcp6(suite) ->
    [];
ttest_sgeno_csockf_small_tcp6(doc) ->
    [];
ttest_sgeno_csockf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockf_small_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgeno_csockf_medium_tcp4(suite) ->
    [];
ttest_sgeno_csockf_medium_tcp4(doc) ->
    [];
ttest_sgeno_csockf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockf_medium_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgeno_csockf_medium_tcp6(suite) ->
    [];
ttest_sgeno_csockf_medium_tcp6(doc) ->
    [];
ttest_sgeno_csockf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockf_medium_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgeno_csockf_large_tcp4(suite) ->
    [];
ttest_sgeno_csockf_large_tcp4(doc) ->
    [];
ttest_sgeno_csockf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockf_large_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgeno_csockf_large_tcp6(suite) ->
    [];
ttest_sgeno_csockf_large_tcp6(doc) ->
    [];
ttest_sgeno_csockf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockf_large_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgeno_csocko_small_tcp4(suite) ->
    [];
ttest_sgeno_csocko_small_tcp4(doc) ->
    [];
ttest_sgeno_csocko_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csocko_small_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgeno_csocko_small_tcp6(suite) ->
    [];
ttest_sgeno_csocko_small_tcp6(doc) ->
    [];
ttest_sgeno_csocko_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csocko_small_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgeno_csocko_medium_tcp4(suite) ->
    [];
ttest_sgeno_csocko_medium_tcp4(doc) ->
    [];
ttest_sgeno_csocko_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csocko_medium_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgeno_csocko_medium_tcp6(suite) ->
    [];
ttest_sgeno_csocko_medium_tcp6(doc) ->
    [];
ttest_sgeno_csocko_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csocko_medium_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgeno_csocko_large_tcp4(suite) ->
    [];
ttest_sgeno_csocko_large_tcp4(doc) ->
    [];
ttest_sgeno_csocko_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csocko_large_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgeno_csocko_large_tcp6(suite) ->
    [];
ttest_sgeno_csocko_large_tcp6(doc) ->
    [];
ttest_sgeno_csocko_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csocko_large_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgeno_csockt_small_tcp4(suite) ->
    [];
ttest_sgeno_csockt_small_tcp4(doc) ->
    [];
ttest_sgeno_csockt_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockt_small_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgeno_csockt_small_tcp6(suite) ->
    [];
ttest_sgeno_csockt_small_tcp6(doc) ->
    [];
ttest_sgeno_csockt_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csocko_small_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgeno_csockt_medium_tcp4(suite) ->
    [];
ttest_sgeno_csockt_medium_tcp4(doc) ->
    [];
ttest_sgeno_csockt_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockt_medium_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgeno_csockt_medium_tcp6(suite) ->
    [];
ttest_sgeno_csockt_medium_tcp6(doc) ->
    [];
ttest_sgeno_csockt_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockt_medium_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgeno_csockt_large_tcp4(suite) ->
    [];
ttest_sgeno_csockt_large_tcp4(doc) ->
    [];
ttest_sgeno_csockt_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockt_large_tcp4,
              Runtime,
              inet,
              gen, once,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgeno_csockt_large_tcp6(suite) ->
    [];
ttest_sgeno_csockt_large_tcp6(doc) ->
    [];
ttest_sgeno_csockt_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgeno_csockt_large_tcp6,
              Runtime,
              inet6,
              gen, once,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgent_cgenf_small_tcp4(suite) ->
    [];
ttest_sgent_cgenf_small_tcp4(doc) ->
    [];
ttest_sgent_cgenf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgenf_small_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgent_cgenf_small_tcp6(suite) ->
    [];
ttest_sgent_cgenf_small_tcp6(doc) ->
    [];
ttest_sgent_cgenf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgenf_small_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgent_cgenf_medium_tcp4(suite) ->
    [];
ttest_sgent_cgenf_medium_tcp4(doc) ->
    [];
ttest_sgent_cgenf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgenf_medium_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgent_cgenf_medium_tcp6(suite) ->
    [];
ttest_sgent_cgenf_medium_tcp6(doc) ->
    [];
ttest_sgent_cgenf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgenf_medium_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgent_cgenf_large_tcp4(suite) ->
    [];
ttest_sgent_cgenf_large_tcp4(doc) ->
    [];
ttest_sgent_cgenf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgenf_large_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgent_cgenf_large_tcp6(suite) ->
    [];
ttest_sgent_cgenf_large_tcp6(doc) ->
    [];
ttest_sgent_cgenf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgenf_large_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgent_cgeno_small_tcp4(suite) ->
    [];
ttest_sgent_cgeno_small_tcp4(doc) ->
    [];
ttest_sgent_cgeno_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgeno_small_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgent_cgeno_small_tcp6(suite) ->
    [];
ttest_sgent_cgeno_small_tcp6(doc) ->
    [];
ttest_sgent_cgeno_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgeno_small_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgent_cgeno_medium_tcp4(suite) ->
    [];
ttest_sgent_cgeno_medium_tcp4(doc) ->
    [];
ttest_sgent_cgeno_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgeno_medium_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgent_cgeno_medium_tcp6(suite) ->
    [];
ttest_sgent_cgeno_medium_tcp6(doc) ->
    [];
ttest_sgent_cgeno_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgeno_medium_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgent_cgeno_large_tcp4(suite) ->
    [];
ttest_sgent_cgeno_large_tcp4(doc) ->
    [];
ttest_sgent_cgeno_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgeno_large_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgent_cgeno_large_tcp6(suite) ->
    [];
ttest_sgent_cgeno_large_tcp6(doc) ->
    [];
ttest_sgent_cgeno_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgeno_large_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgent_cgent_small_tcp4(suite) ->
    [];
ttest_sgent_cgent_small_tcp4(doc) ->
    [];
ttest_sgent_cgent_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgent_small_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgent_cgent_small_tcp6(suite) ->
    [];
ttest_sgent_cgent_small_tcp6(doc) ->
    [];
ttest_sgent_cgent_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgeno_small_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgent_cgent_medium_tcp4(suite) ->
    [];
ttest_sgent_cgent_medium_tcp4(doc) ->
    ["Server(gen,true), Client(gen,true), Domain=inet, msg=medium"];
ttest_sgent_cgent_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgent_medium_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgent_cgent_medium_tcp6(suite) ->
    [];
ttest_sgent_cgent_medium_tcp6(doc) ->
    ["Server(gen,true), Client(gen,true), Domain=inet6, msg=medium"];
ttest_sgent_cgent_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgent_medium_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgent_cgent_large_tcp4(suite) ->
    [];
ttest_sgent_cgent_large_tcp4(doc) ->
    ["Server(gen,true), Client(gen,true), Domain=inet, msg=large"];
ttest_sgent_cgent_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgent_large_tcp4,
              Runtime,
              inet,
              gen, true,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgent_cgent_large_tcp6(suite) ->
    [];
ttest_sgent_cgent_large_tcp6(doc) ->
    ["Server(gen,true), Client(gen,true), Domain=inet6, msg=large"];
ttest_sgent_cgent_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_cgent_large_tcp6,
              Runtime,
              inet6,
              gen, true,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgent_csockf_small_tcp4(suite) ->
    [];
ttest_sgent_csockf_small_tcp4(doc) ->
    [];
ttest_sgent_csockf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockf_small_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgent_csockf_small_tcp6(suite) ->
    [];
ttest_sgent_csockf_small_tcp6(doc) ->
    [];
ttest_sgent_csockf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockf_small_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgent_csockf_medium_tcp4(suite) ->
    [];
ttest_sgent_csockf_medium_tcp4(doc) ->
    [];
ttest_sgent_csockf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockf_medium_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgent_csockf_medium_tcp6(suite) ->
    [];
ttest_sgent_csockf_medium_tcp6(doc) ->
    [];
ttest_sgent_csockf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockf_medium_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgent_csockf_large_tcp4(suite) ->
    [];
ttest_sgent_csockf_large_tcp4(doc) ->
    [];
ttest_sgent_csockf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockf_large_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgent_csockf_large_tcp6(suite) ->
    [];
ttest_sgent_csockf_large_tcp6(doc) ->
    [];
ttest_sgent_csockf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockf_large_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgent_csocko_small_tcp4(suite) ->
    [];
ttest_sgent_csocko_small_tcp4(doc) ->
    [];
ttest_sgent_csocko_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csocko_small_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgent_csocko_small_tcp6(suite) ->
    [];
ttest_sgent_csocko_small_tcp6(doc) ->
    [];
ttest_sgent_csocko_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csocko_small_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgent_csocko_medium_tcp4(suite) ->
    [];
ttest_sgent_csocko_medium_tcp4(doc) ->
    [];
ttest_sgent_csocko_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csocko_medium_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgent_csocko_medium_tcp6(suite) ->
    [];
ttest_sgent_csocko_medium_tcp6(doc) ->
    [];
ttest_sgent_csocko_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csocko_medium_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgent_csocko_large_tcp4(suite) ->
    [];
ttest_sgent_csocko_large_tcp4(doc) ->
    [];
ttest_sgent_csocko_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csocko_large_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgent_csocko_large_tcp6(suite) ->
    [];
ttest_sgent_csocko_large_tcp6(doc) ->
    [];
ttest_sgent_csocko_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csocko_large_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_sgent_csockt_small_tcp4(suite) ->
    [];
ttest_sgent_csockt_small_tcp4(doc) ->
    [];
ttest_sgent_csockt_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockt_small_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_sgent_csockt_small_tcp6(suite) ->
    [];
ttest_sgent_csockt_small_tcp6(doc) ->
    [];
ttest_sgent_csockt_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csocko_small_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_sgent_csockt_medium_tcp4(suite) ->
    [];
ttest_sgent_csockt_medium_tcp4(doc) ->
    [];
ttest_sgent_csockt_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockt_medium_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_sgent_csockt_medium_tcp6(suite) ->
    [];
ttest_sgent_csockt_medium_tcp6(doc) ->
    [];
ttest_sgent_csockt_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockt_medium_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_sgent_csockt_large_tcp4(suite) ->
    [];
ttest_sgent_csockt_large_tcp4(doc) ->
    [];
ttest_sgent_csockt_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockt_large_tcp4,
              Runtime,
              inet,
              gen, true,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = gen_tcp, Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_sgent_csockt_large_tcp6(suite) ->
    [];
ttest_sgent_csockt_large_tcp6(doc) ->
    [];
ttest_sgent_csockt_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_sgent_csockt_large_tcp6,
              Runtime,
              inet6,
              gen, true,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockf_cgenf_small_tcp4(suite) ->
    [];
ttest_ssockf_cgenf_small_tcp4(doc) ->
    [];
ttest_ssockf_cgenf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgenf_small_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockf_cgenf_small_tcp6(suite) ->
    [];
ttest_ssockf_cgenf_small_tcp6(doc) ->
    [];
ttest_ssockf_cgenf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgenf_small_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockf_cgenf_medium_tcp4(suite) ->
    [];
ttest_ssockf_cgenf_medium_tcp4(doc) ->
    [];
ttest_ssockf_cgenf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgenf_medium_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockf_cgenf_medium_tcp6(suite) ->
    [];
ttest_ssockf_cgenf_medium_tcp6(doc) ->
    [];
ttest_ssockf_cgenf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgenf_medium_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockf_cgenf_large_tcp4(suite) ->
    [];
ttest_ssockf_cgenf_large_tcp4(doc) ->
    [];
ttest_ssockf_cgenf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgenf_large_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockf_cgenf_large_tcp6(suite) ->
    [];
ttest_ssockf_cgenf_large_tcp6(doc) ->
    [];
ttest_ssockf_cgenf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgenf_large_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockf_cgeno_small_tcp4(suite) ->
    [];
ttest_ssockf_cgeno_small_tcp4(doc) ->
    [];
ttest_ssockf_cgeno_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgeno_small_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockf_cgeno_small_tcp6(suite) ->
    [];
ttest_ssockf_cgeno_small_tcp6(doc) ->
    [];
ttest_ssockf_cgeno_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgeno_small_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockf_cgeno_medium_tcp4(suite) ->
    [];
ttest_ssockf_cgeno_medium_tcp4(doc) ->
    [];
ttest_ssockf_cgeno_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgeno_medium_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockf_cgeno_medium_tcp6(suite) ->
    [];
ttest_ssockf_cgeno_medium_tcp6(doc) ->
    [];
ttest_ssockf_cgeno_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgeno_medium_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockf_cgeno_large_tcp4(suite) ->
    [];
ttest_ssockf_cgeno_large_tcp4(doc) ->
    [];
ttest_ssockf_cgeno_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgeno_large_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockf_cgeno_large_tcp6(suite) ->
    [];
ttest_ssockf_cgeno_large_tcp6(doc) ->
    [];
ttest_ssockf_cgeno_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgeno_large_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockf_cgent_small_tcp4(suite) ->
    [];
ttest_ssockf_cgent_small_tcp4(doc) ->
    [];
ttest_ssockf_cgent_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgent_small_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockf_cgent_small_tcp6(suite) ->
    [];
ttest_ssockf_cgent_small_tcp6(doc) ->
    [];
ttest_ssockf_cgent_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgeno_small_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockf_cgent_medium_tcp4(suite) ->
    [];
ttest_ssockf_cgent_medium_tcp4(doc) ->
    [];
ttest_ssockf_cgent_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgent_medium_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockf_cgent_medium_tcp6(suite) ->
    [];
ttest_ssockf_cgent_medium_tcp6(doc) ->
    [];
ttest_ssockf_cgent_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgent_medium_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockf_cgent_large_tcp4(suite) ->
    [];
ttest_ssockf_cgent_large_tcp4(doc) ->
    [];
ttest_ssockf_cgent_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgent_large_tcp4,
              Runtime,
              inet,
              sock, false,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockf_cgent_large_tcp6(suite) ->
    [];
ttest_ssockf_cgent_large_tcp6(doc) ->
    [];
ttest_ssockf_cgent_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_cgent_large_tcp6,
              Runtime,
              inet6,
              sock, false,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockf_csockf_small_tcp4(suite) ->
    [];
ttest_ssockf_csockf_small_tcp4(doc) ->
    [];
ttest_ssockf_csockf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_small_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockf_csockf_small_tcp6(suite) ->
    [];
ttest_ssockf_csockf_small_tcp6(doc) ->
    [];
ttest_ssockf_csockf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_small_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssockf_csockf_small_tcpL(suite) ->
    [];
ttest_ssockf_csockf_small_tcpL(doc) ->
    [];
ttest_ssockf_csockf_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_small_tcpL,
              Runtime,
              local,
              sock, false,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockf_csockf_medium_tcp4(suite) ->
    [];
ttest_ssockf_csockf_medium_tcp4(doc) ->
    [];
ttest_ssockf_csockf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_medium_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockf_csockf_medium_tcp6(suite) ->
    [];
ttest_ssockf_csockf_medium_tcp6(doc) ->
    [];
ttest_ssockf_csockf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_medium_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssockf_csockf_medium_tcpL(suite) ->
    [];
ttest_ssockf_csockf_medium_tcpL(doc) ->
    [];
ttest_ssockf_csockf_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_medium_tcpL,
              Runtime,
              local,
              sock, false,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockf_csockf_large_tcp4(suite) ->
    [];
ttest_ssockf_csockf_large_tcp4(doc) ->
    [];
ttest_ssockf_csockf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_large_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockf_csockf_large_tcp6(suite) ->
    [];
ttest_ssockf_csockf_large_tcp6(doc) ->
    [];
ttest_ssockf_csockf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_large_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssockf_csockf_large_tcpL(suite) ->
    [];
ttest_ssockf_csockf_large_tcpL(doc) ->
    [];
ttest_ssockf_csockf_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockf_large_tcpL,
              Runtime,
              local,
              sock, false,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockf_csocko_small_tcp4(suite) ->
    [];
ttest_ssockf_csocko_small_tcp4(doc) ->
    [];
ttest_ssockf_csocko_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_small_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockf_csocko_small_tcp6(suite) ->
    [];
ttest_ssockf_csocko_small_tcp6(doc) ->
    [];
ttest_ssockf_csocko_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_small_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssockf_csocko_small_tcpL(suite) ->
    [];
ttest_ssockf_csocko_small_tcpL(doc) ->
    [];
ttest_ssockf_csocko_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_small_tcpL,
              Runtime,
              local,
              sock, false,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockf_csocko_medium_tcp4(suite) ->
    [];
ttest_ssockf_csocko_medium_tcp4(doc) ->
    [];
ttest_ssockf_csocko_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_medium_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockf_csocko_medium_tcp6(suite) ->
    [];
ttest_ssockf_csocko_medium_tcp6(doc) ->
    [];
ttest_ssockf_csocko_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_medium_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssockf_csocko_medium_tcpL(suite) ->
    [];
ttest_ssockf_csocko_medium_tcpL(doc) ->
    [];
ttest_ssockf_csocko_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_medium_tcpL,
              Runtime,
              local,
              sock, false,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockf_csocko_large_tcp4(suite) ->
    [];
ttest_ssockf_csocko_large_tcp4(doc) ->
    [];
ttest_ssockf_csocko_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_large_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockf_csocko_large_tcp6(suite) ->
    [];
ttest_ssockf_csocko_large_tcp6(doc) ->
    [];
ttest_ssockf_csocko_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_large_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssockf_csocko_large_tcpL(suite) ->
    [];
ttest_ssockf_csocko_large_tcpL(doc) ->
    [];
ttest_ssockf_csocko_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_large_tcpL,
              Runtime,
              local,
              sock, false,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockf_csockt_small_tcp4(suite) ->
    [];
ttest_ssockf_csockt_small_tcp4(doc) ->
    [];
ttest_ssockf_csockt_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockt_small_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockf_csockt_small_tcp6(suite) ->
    [];
ttest_ssockf_csockt_small_tcp6(doc) ->
    [];
ttest_ssockf_csockt_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_small_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssockf_csockt_small_tcpL(suite) ->
    [];
ttest_ssockf_csockt_small_tcpL(doc) ->
    [];
ttest_ssockf_csockt_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csocko_small_tcpL,
              Runtime,
              local,
              sock, false,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockf_csockt_medium_tcp4(suite) ->
    [];
ttest_ssockf_csockt_medium_tcp4(doc) ->
    [];
ttest_ssockf_csockt_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockt_medium_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockf_csockt_medium_tcp6(suite) ->
    [];
ttest_ssockf_csockt_medium_tcp6(doc) ->
    [];
ttest_ssockf_csockt_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockt_medium_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssockf_csockt_medium_tcpL(suite) ->
    [];
ttest_ssockf_csockt_medium_tcpL(doc) ->
    [];
ttest_ssockf_csockt_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockt_medium_tcpL,
              Runtime,
              local,
              sock, false,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockf_csockt_large_tcp4(suite) ->
    [];
ttest_ssockf_csockt_large_tcp4(doc) ->
    [];
ttest_ssockf_csockt_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockt_large_tcp4,
              Runtime,
              inet,
              sock, false,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockf_csockt_large_tcp6(suite) ->
    [];
ttest_ssockf_csockt_large_tcp6(doc) ->
    [];
ttest_ssockf_csockt_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockt_large_tcp6,
              Runtime,
              inet6,
              sock, false,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssockf_csockt_large_tcpL(suite) ->
    [];
ttest_ssockf_csockt_large_tcpL(doc) ->
    [];
ttest_ssockf_csockt_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockf_csockt_large_tcpL,
              Runtime,
              local,
              sock, false,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssocko_cgenf_small_tcp4(suite) ->
    [];
ttest_ssocko_cgenf_small_tcp4(doc) ->
    [];
ttest_ssocko_cgenf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgenf_small_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssocko_cgenf_small_tcp6(suite) ->
    [];
ttest_ssocko_cgenf_small_tcp6(doc) ->
    [];
ttest_ssocko_cgenf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgenf_small_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssocko_cgenf_medium_tcp4(suite) ->
    [];
ttest_ssocko_cgenf_medium_tcp4(doc) ->
    [];
ttest_ssocko_cgenf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgenf_medium_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssocko_cgenf_medium_tcp6(suite) ->
    [];
ttest_ssocko_cgenf_medium_tcp6(doc) ->
    [];
ttest_ssocko_cgenf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgenf_medium_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssocko_cgenf_large_tcp4(suite) ->
    [];
ttest_ssocko_cgenf_large_tcp4(doc) ->
    [];
ttest_ssocko_cgenf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgenf_large_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssocko_cgenf_large_tcp6(suite) ->
    [];
ttest_ssocko_cgenf_large_tcp6(doc) ->
    [];
ttest_ssocko_cgenf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgenf_large_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssocko_cgeno_small_tcp4(suite) ->
    [];
ttest_ssocko_cgeno_small_tcp4(doc) ->
    [];
ttest_ssocko_cgeno_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgeno_small_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssocko_cgeno_small_tcp6(suite) ->
    [];
ttest_ssocko_cgeno_small_tcp6(doc) ->
    [];
ttest_ssocko_cgeno_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgeno_small_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssocko_cgeno_medium_tcp4(suite) ->
    [];
ttest_ssocko_cgeno_medium_tcp4(doc) ->
    [];
ttest_ssocko_cgeno_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgeno_medium_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssocko_cgeno_medium_tcp6(suite) ->
    [];
ttest_ssocko_cgeno_medium_tcp6(doc) ->
    [];
ttest_ssocko_cgeno_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgeno_medium_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssocko_cgeno_large_tcp4(suite) ->
    [];
ttest_ssocko_cgeno_large_tcp4(doc) ->
    [];
ttest_ssocko_cgeno_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgeno_large_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssocko_cgeno_large_tcp6(suite) ->
    [];
ttest_ssocko_cgeno_large_tcp6(doc) ->
    [];
ttest_ssocko_cgeno_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgeno_large_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssocko_cgent_small_tcp4(suite) ->
    [];
ttest_ssocko_cgent_small_tcp4(doc) ->
    [];
ttest_ssocko_cgent_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgent_small_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssocko_cgent_small_tcp6(suite) ->
    [];
ttest_ssocko_cgent_small_tcp6(doc) ->
    [];
ttest_ssocko_cgent_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgent_small_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssocko_cgent_medium_tcp4(suite) ->
    [];
ttest_ssocko_cgent_medium_tcp4(doc) ->
    [];
ttest_ssocko_cgent_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgent_medium_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssocko_cgent_medium_tcp6(suite) ->
    [];
ttest_ssocko_cgent_medium_tcp6(doc) ->
    [];
ttest_ssocko_cgent_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgent_medium_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssocko_cgent_large_tcp4(suite) ->
    [];
ttest_ssocko_cgent_large_tcp4(doc) ->
    [];
ttest_ssocko_cgent_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgent_large_tcp4,
              Runtime,
              inet,
              sock, once,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = false
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssocko_cgent_large_tcp6(suite) ->
    [];
ttest_ssocko_cgent_large_tcp6(doc) ->
    [];
ttest_ssocko_cgent_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_cgent_large_tcp6,
              Runtime,
              inet6,
              sock, once,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssocko_csockf_small_tcp4(suite) ->
    [];
ttest_ssocko_csockf_small_tcp4(doc) ->
    [];
ttest_ssocko_csockf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_small_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssocko_csockf_small_tcp6(suite) ->
    [];
ttest_ssocko_csockf_small_tcp6(doc) ->
    [];
ttest_ssocko_csockf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_small_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssocko_csockf_small_tcpL(suite) ->
    [];
ttest_ssocko_csockf_small_tcpL(doc) ->
    [];
ttest_ssocko_csockf_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_small_tcpL,
              Runtime,
              local,
              sock, once,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssocko_csockf_medium_tcp4(suite) ->
    [];
ttest_ssocko_csockf_medium_tcp4(doc) ->
    [];
ttest_ssocko_csockf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_medium_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssocko_csockf_medium_tcp6(suite) ->
    [];
ttest_ssocko_csockf_medium_tcp6(doc) ->
    [];
ttest_ssocko_csockf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_medium_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssocko_csockf_medium_tcpL(suite) ->
    [];
ttest_ssocko_csockf_medium_tcpL(doc) ->
    [];
ttest_ssocko_csockf_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_medium_tcpL,
              Runtime,
              local,
              sock, once,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssocko_csockf_large_tcp4(suite) ->
    [];
ttest_ssocko_csockf_large_tcp4(doc) ->
    [];
ttest_ssocko_csockf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_large_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssocko_csockf_large_tcp6(suite) ->
    [];
ttest_ssocko_csockf_large_tcp6(doc) ->
    [];
ttest_ssocko_csockf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_large_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssocko_csockf_large_tcpL(suite) ->
    [];
ttest_ssocko_csockf_large_tcpL(doc) ->
    [];
ttest_ssocko_csockf_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockf_large_tcpL,
              Runtime,
              local,
              sock, once,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssocko_csocko_small_tcp4(suite) ->
    [];
ttest_ssocko_csocko_small_tcp4(doc) ->
    [];
ttest_ssocko_csocko_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_small_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssocko_csocko_small_tcp6(suite) ->
    [];
ttest_ssocko_csocko_small_tcp6(doc) ->
    [];
ttest_ssocko_csocko_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_small_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssocko_csocko_small_tcpL(suite) ->
    [];
ttest_ssocko_csocko_small_tcpL(doc) ->
    [];
ttest_ssocko_csocko_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_small_tcpL,
              Runtime,
              local,
              sock, once,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssocko_csocko_medium_tcp4(suite) ->
    [];
ttest_ssocko_csocko_medium_tcp4(doc) ->
    [];
ttest_ssocko_csocko_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_medium_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssocko_csocko_medium_tcp6(suite) ->
    [];
ttest_ssocko_csocko_medium_tcp6(doc) ->
    [];
ttest_ssocko_csocko_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_medium_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssocko_csocko_medium_tcpL(suite) ->
    [];
ttest_ssocko_csocko_medium_tcpL(doc) ->
    [];
ttest_ssocko_csocko_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_medium_tcpL,
              Runtime,
              local,
              sock, once,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssocko_csocko_large_tcp4(suite) ->
    [];
ttest_ssocko_csocko_large_tcp4(doc) ->
    [];
ttest_ssocko_csocko_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_large_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssocko_csocko_large_tcp6(suite) ->
    [];
ttest_ssocko_csocko_large_tcp6(doc) ->
    [];
ttest_ssocko_csocko_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_large_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssocko_csocko_large_tcpL(suite) ->
    [];
ttest_ssocko_csocko_large_tcpL(doc) ->
    [];
ttest_ssocko_csocko_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_large_tcpL,
              Runtime,
              local,
              sock, once,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssocko_csockt_small_tcp4(suite) ->
    [];
ttest_ssocko_csockt_small_tcp4(doc) ->
    [];
ttest_ssocko_csockt_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockt_small_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssocko_csockt_small_tcp6(suite) ->
    [];
ttest_ssocko_csockt_small_tcp6(doc) ->
    [];
ttest_ssocko_csockt_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_small_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssocko_csockt_small_tcpL(suite) ->
    [];
ttest_ssocko_csockt_small_tcpL(doc) ->
    [];
ttest_ssocko_csockt_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csocko_small_tcpL,
              Runtime,
              local,
              sock, once,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssocko_csockt_medium_tcp4(suite) ->
    [];
ttest_ssocko_csockt_medium_tcp4(doc) ->
    [];
ttest_ssocko_csockt_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockt_medium_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssocko_csockt_medium_tcp6(suite) ->
    [];
ttest_ssocko_csockt_medium_tcp6(doc) ->
    [];
ttest_ssocko_csockt_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockt_medium_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssocko_csockt_medium_tcpL(suite) ->
    [];
ttest_ssocko_csockt_medium_tcpL(doc) ->
    [];
ttest_ssocko_csockt_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockt_medium_tcpL,
              Runtime,
              local,
              sock, once,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssocko_csockt_large_tcp4(suite) ->
    [];
ttest_ssocko_csockt_large_tcp4(doc) ->
    [];
ttest_ssocko_csockt_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockt_large_tcp4,
              Runtime,
              inet,
              sock, once,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssocko_csockt_large_tcp6(suite) ->
    [];
ttest_ssocko_csockt_large_tcp6(doc) ->
    [];
ttest_ssocko_csockt_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockt_large_tcp6,
              Runtime,
              inet6,
              sock, once,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = once
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssocko_csockt_large_tcpL(suite) ->
    [];
ttest_ssocko_csockt_large_tcpL(doc) ->
    [];
ttest_ssocko_csockt_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssocko_csockt_large_tcpL,
              Runtime,
              local,
              sock, once,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockt_cgenf_small_tcp4(suite) ->
    [];
ttest_ssockt_cgenf_small_tcp4(doc) ->
    [];
ttest_ssockt_cgenf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgenf_small_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockt_cgenf_small_tcp6(suite) ->
    [];
ttest_ssockt_cgenf_small_tcp6(doc) ->
    [];
ttest_ssockt_cgenf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgenf_small_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockt_cgenf_medium_tcp4(suite) ->
    [];
ttest_ssockt_cgenf_medium_tcp4(doc) ->
    [];
ttest_ssockt_cgenf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgenf_medium_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockt_cgenf_medium_tcp6(suite) ->
    [];
ttest_ssockt_cgenf_medium_tcp6(doc) ->
    [];
ttest_ssockt_cgenf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgenf_medium_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockt_cgenf_large_tcp4(suite) ->
    [];
ttest_ssockt_cgenf_large_tcp4(doc) ->
    [];
ttest_ssockt_cgenf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgenf_large_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockt_cgenf_large_tcp6(suite) ->
    [];
ttest_ssockt_cgenf_large_tcp6(doc) ->
    [];
ttest_ssockt_cgenf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgenf_large_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockt_cgeno_small_tcp4(suite) ->
    [];
ttest_ssockt_cgeno_small_tcp4(doc) ->
    [];
ttest_ssockt_cgeno_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgeno_small_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockt_cgeno_small_tcp6(suite) ->
    [];
ttest_ssockt_cgeno_small_tcp6(doc) ->
    [];
ttest_ssockt_cgeno_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgeno_small_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockt_cgeno_medium_tcp4(suite) ->
    [];
ttest_ssockt_cgeno_medium_tcp4(doc) ->
    [];
ttest_ssockt_cgeno_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgeno_medium_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockt_cgeno_medium_tcp6(suite) ->
    [];
ttest_ssockt_cgeno_medium_tcp6(doc) ->
    [];
ttest_ssockt_cgeno_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgeno_medium_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockt_cgeno_large_tcp4(suite) ->
    [];
ttest_ssockt_cgeno_large_tcp4(doc) ->
    [];
ttest_ssockt_cgeno_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgeno_large_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockt_cgeno_large_tcp6(suite) ->
    [];
ttest_ssockt_cgeno_large_tcp6(doc) ->
    [];
ttest_ssockt_cgeno_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgeno_large_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockt_cgent_small_tcp4(suite) ->
    [];
ttest_ssockt_cgent_small_tcp4(doc) ->
    [];
ttest_ssockt_cgent_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgent_small_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockt_cgent_small_tcp6(suite) ->
    [];
ttest_ssockt_cgent_small_tcp6(doc) ->
    [];
ttest_ssockt_cgent_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgent_small_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockt_cgent_medium_tcp4(suite) ->
    [];
ttest_ssockt_cgent_medium_tcp4(doc) ->
    [];
ttest_ssockt_cgent_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgent_medium_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockt_cgent_medium_tcp6(suite) ->
    [];
ttest_ssockt_cgent_medium_tcp6(doc) ->
    [];
ttest_ssockt_cgent_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgent_medium_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockt_cgent_large_tcp4(suite) ->
    [];
ttest_ssockt_cgent_large_tcp4(doc) ->
    [];
ttest_ssockt_cgent_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgent_large_tcp4,
              Runtime,
              inet,
              sock, true,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = gen_tcp, Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockt_cgent_large_tcp6(suite) ->
    [];
ttest_ssockt_cgent_large_tcp6(doc) ->
    [];
ttest_ssockt_cgent_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_cgent_large_tcp6,
              Runtime,
              inet6,
              sock, true,
              gen, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockt_csockf_small_tcp4(suite) ->
    [];
ttest_ssockt_csockf_small_tcp4(doc) ->
    [];
ttest_ssockt_csockf_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_small_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockt_csockf_small_tcp6(suite) ->
    [];
ttest_ssockt_csockf_small_tcp6(doc) ->
    [];
ttest_ssockt_csockf_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_small_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssockt_csockf_small_tcpL(suite) ->
    [];
ttest_ssockt_csockf_small_tcpL(doc) ->
    [];
ttest_ssockt_csockf_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_small_tcpL,
              Runtime,
              local,
              sock, true,
              sock, false,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockt_csockf_medium_tcp4(suite) ->
    [];
ttest_ssockt_csockf_medium_tcp4(doc) ->
    [];
ttest_ssockt_csockf_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_medium_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockt_csockf_medium_tcp6(suite) ->
    [];
ttest_ssockt_csockf_medium_tcp6(doc) ->
    [];
ttest_ssockt_csockf_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_medium_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssockt_csockf_medium_tcpL(suite) ->
    [];
ttest_ssockt_csockf_medium_tcpL(doc) ->
    [];
ttest_ssockt_csockf_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_medium_tcpL,
              Runtime,
              local,
              sock, true,
              sock, false,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockt_csockf_large_tcp4(suite) ->
    [];
ttest_ssockt_csockf_large_tcp4(doc) ->
    [];
ttest_ssockt_csockf_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_large_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockt_csockf_large_tcp6(suite) ->
    [];
ttest_ssockt_csockf_large_tcp6(doc) ->
    [];
ttest_ssockt_csockf_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_large_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = false
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssockt_csockf_large_tcpL(suite) ->
    [];
ttest_ssockt_csockf_large_tcpL(doc) ->
    [];
ttest_ssockt_csockf_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockf_large_tcpL,
              Runtime,
              local,
              sock, true,
              sock, false,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockt_csocko_small_tcp4(suite) ->
    [];
ttest_ssockt_csocko_small_tcp4(doc) ->
    [];
ttest_ssockt_csocko_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_small_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockt_csocko_small_tcp6(suite) ->
    [];
ttest_ssockt_csocko_small_tcp6(doc) ->
    [];
ttest_ssockt_csocko_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_small_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssockt_csocko_small_tcpL(suite) ->
    [];
ttest_ssockt_csocko_small_tcpL(doc) ->
    [];
ttest_ssockt_csocko_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_small_tcpL,
              Runtime,
              local,
              sock, true,
              sock, once,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockt_csocko_medium_tcp4(suite) ->
    [];
ttest_ssockt_csocko_medium_tcp4(doc) ->
    [];
ttest_ssockt_csocko_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_medium_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockt_csocko_medium_tcp6(suite) ->
    [];
ttest_ssockt_csocko_medium_tcp6(doc) ->
    [];
ttest_ssockt_csocko_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_medium_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssockt_csocko_medium_tcpL(suite) ->
    [];
ttest_ssockt_csocko_medium_tcpL(doc) ->
    [];
ttest_ssockt_csocko_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_medium_tcpL,
              Runtime,
              local,
              sock, true,
              sock, once,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockt_csocko_large_tcp4(suite) ->
    [];
ttest_ssockt_csocko_large_tcp4(doc) ->
    [];
ttest_ssockt_csocko_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_large_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockt_csocko_large_tcp6(suite) ->
    [];
ttest_ssockt_csocko_large_tcp6(doc) ->
    [];
ttest_ssockt_csocko_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_large_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = once
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssockt_csocko_large_tcpL(suite) ->
    [];
ttest_ssockt_csocko_large_tcpL(doc) ->
    [];
ttest_ssockt_csocko_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_large_tcpL,
              Runtime,
              local,
              sock, true,
              sock, once,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet
%%

ttest_ssockt_csockt_small_tcp4(suite) ->
    [];
ttest_ssockt_csockt_small_tcp4(doc) ->
    [];
ttest_ssockt_csockt_small_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockt_small_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       inet6
%% 

ttest_ssockt_csockt_small_tcp6(suite) ->
    [];
ttest_ssockt_csockt_small_tcp6(doc) ->
    [];
ttest_ssockt_csockt_small_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_small_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport =  socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: small (=1)
%% Domain:       local
%% 

ttest_ssockt_csockt_small_tcpL(suite) ->
    [];
ttest_ssockt_csockt_small_tcpL(doc) ->
    [];
ttest_ssockt_csockt_small_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csocko_small_tcpL,
              Runtime,
              local,
              sock, true,
              sock, true,
              1, 200).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet
%%

ttest_ssockt_csockt_medium_tcp4(suite) ->
    [];
ttest_ssockt_csockt_medium_tcp4(doc) ->
    [];
ttest_ssockt_csockt_medium_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockt_medium_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       inet6
%% 

ttest_ssockt_csockt_medium_tcp6(suite) ->
    [];
ttest_ssockt_csockt_medium_tcp6(doc) ->
    [];
ttest_ssockt_csockt_medium_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockt_medium_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: medium (=2)
%% Domain:       local
%% 

ttest_ssockt_csockt_medium_tcpL(suite) ->
    [];
ttest_ssockt_csockt_medium_tcpL(doc) ->
    [];
ttest_ssockt_csockt_medium_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockt_medium_tcpL,
              Runtime,
              local,
              sock, true,
              sock, true,
              2, 20).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet
%%

ttest_ssockt_csockt_large_tcp4(suite) ->
    [];
ttest_ssockt_csockt_large_tcp4(doc) ->
    [];
ttest_ssockt_csockt_large_tcp4(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockt_large_tcp4,
              Runtime,
              inet,
              sock, true,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       inet6
%% 

ttest_ssockt_csockt_large_tcp6(suite) ->
    [];
ttest_ssockt_csockt_large_tcp6(doc) ->
    [];
ttest_ssockt_csockt_large_tcp6(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockt_large_tcp6,
              Runtime,
              inet6,
              sock, true,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case uses the time test (ttest) utility to implement a 
%% ping-pong like test case.
%% Server:       Transport = socket(tcp), Active = true
%% Client:       Transport = socket(tcp), Active = true
%% Message Size: large (=3)
%% Domain:       local
%% 

ttest_ssockt_csockt_large_tcpL(suite) ->
    [];
ttest_ssockt_csockt_large_tcpL(doc) ->
    [];
ttest_ssockt_csockt_large_tcpL(Config) when is_list(Config) ->
    Runtime = which_ttest_runtime(Config),
    ttest_tcp(ttest_ssockt_csockt_large_tcpL,
              Runtime,
              local,
              sock, true,
              sock, true,
              3, 2).



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

which_ttest_runtime(Config) when is_list(Config) ->
    case lists:keysearch(esock_test_ttest_runtime, 1, Config) of
        {value, {esock_test_ttest_runtime, Runtime}} ->
            Runtime;
        false ->
            which_ttest_runtime_env()
    end.

which_ttest_runtime_env() ->
    which_ttest_runtime_env(os:getenv("ESOCK_TEST_TTEST_RUNTIME")).

which_ttest_runtime_env(TStr) when is_list(TStr) ->
    which_ttest_runtime_env2(lists:reverse(TStr));
which_ttest_runtime_env(false) ->
    ?TTEST_RUNTIME.


%% The format is: <int>[unit]
%% where the optional unit can be:
%% ms: milliseconds
%% s:  seconds (default)
%% m:  minutes
which_ttest_runtime_env2([$s, $m | MS]) when (length(MS) > 0) ->
    convert_time(MS, fun(X) -> X end);
which_ttest_runtime_env2([$m | M]) when (length(M) > 0) ->
    convert_time(M, fun(X) -> ?MINS(X) end);
which_ttest_runtime_env2([$s | S]) when (length(S) > 0) ->
    convert_time(S, fun(X) -> ?SECS(X) end);
which_ttest_runtime_env2(S) ->
    convert_time(S, fun(X) -> ?SECS(X) end).

convert_time(TStrRev, Convert) ->
    try list_to_integer(lists:reverse(TStrRev)) of
        I -> Convert(I)
    catch
        _:_ ->
            ?TTEST_RUNTIME
    end.

%% ttest_tcp(TC,
%%           Domain,
%%           ServerMod, ServerActive,
%%           ClientMod, ClientActive,
%%           MsgID, MaxOutstanding) ->
%%     ttest_tcp(TC,
%%               ?TTEST_RUNTIME,
%%               Domain,
%%               ServerMod, ServerActive,
%%               ClientMod, ClientActive,
%%               MsgID, MaxOutstanding).
ttest_tcp(TC,
          Runtime,
          Domain,
          ServerMod, ServerActive,
          ClientMod, ClientActive,
          MsgID, MaxOutstanding) ->
    tc_try(TC,
           fun() ->
                   if
                       (Domain =:= local) -> has_support_unix_domain_socket(); 
                       (Domain =:= inet6) -> has_support_ipv6(); 
                       true -> ok 
                   end
           end,
           fun() ->
                   %% This may be overkill, depending on the runtime,
                   %% but better safe then sorry...
                   ?TT(Runtime + ?SECS(60)),
                   InitState = #{domain          => Domain,
                                 msg_id          => MsgID,
                                 max_outstanding => MaxOutstanding,
                                 runtime         => Runtime,
                                 server_mod      => ServerMod,
                                 server_active   => ServerActive,
                                 client_mod      => ClientMod,
                                 client_active   => ClientActive},
                   ok = ttest_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ttest_tcp(InitState) ->
    ServerSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(State) ->
                           Tester = ?SEV_AWAIT_START(),
                           {ok, State#{tester => Tester}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},


         %% *** Init part ***
         #{desc => "create node",
           cmd  => fun(#{host := Host} = State) ->
                           case start_node(Host, server) of
                               {ok, Node} ->
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor server node",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "start ttest (remote) server",
           cmd  => fun(#{domain := local = Domain,
                         mod    := Mod,
                         active := Active,
                         node   := Node} = State) ->
                           case ttest_tcp_server_start(Node,
                                                       Domain, Mod, Active) of
                               {ok, {{Pid, _}, Path}} ->
                                   {ok, State#{rserver => Pid,
                                               path    => Path}};
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{domain := Domain,
                         mod    := Mod,
                         active := Active,
                         node   := Node} = State) ->
                           case ttest_tcp_server_start(Node,
                                                       Domain, Mod, Active) of
                               {ok, {{Pid, _}, {Addr, Port}}} ->
                                   {ok, State#{rserver => Pid,
                                               addr    => Addr,
                                               port    => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain := local,
                         tester := Tester,
                         path   := Path}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, Path),
                           ok;
                      (#{tester := Tester,
                         addr   := Addr,
                         port   := Port}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init, {Addr, Port}),
                           ok
                   end},


         %% *** Termination ***
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester  := Tester, 
                         rserver := RServer} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester,
                                                     [{rserver, RServer}]) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         %% The remote server is in a accept, with a timeout of 5 seconds,
         %% so may have to wait a bit...
         #{desc => "order (remote) ttest server terminate",
           cmd  => fun(#{node    := _Node,
                         rserver := RServer}) ->
                           ttest_tcp_server_stop(RServer),
                           ok
                   end},
         #{desc => "await ttest (remote) server termination",
           cmd  => fun(#{rserver := RServer} = State) ->
                           ?SEV_AWAIT_TERMINATION(RServer),
                           State1 = maps:remove(rserver, State),
                           {ok, State1}
                   end},
         #{desc => "stop (server) node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await (server) node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   {ok, maps:remove(node, State)}
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{desc => "await start",
           cmd  => fun(#{domain := local} = State) ->
                           {Tester, ServerPath} = 
                               ?SEV_AWAIT_START(),
                           {ok, State#{tester      => Tester,
                                       server_path => ServerPath}};
                      (State) ->
                           {Tester, {ServerAddr, ServerPort}} = 
                               ?SEV_AWAIT_START(),
                           {ok, State#{tester      => Tester,
                                       server_addr => ServerAddr,
                                       server_port => ServerPort}}
                   end},
         #{desc => "monitor tester",
           cmd  => fun(#{tester := Tester} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},


         %% *** Init part ***
         #{desc => "create node",
           cmd  => fun(#{host := Host} = State) ->
                           case start_node(Host, client) of
                               {ok, Node} ->
                                   {ok, State#{node => Node}};
                               {error, Reason} ->
                                   {skip, Reason}
                           end
                   end},
         #{desc => "monitor client node",
           cmd  => fun(#{node := Node} = _State) ->
                           true = erlang:monitor_node(Node, true),
                           ok
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},


         %% The actual test
         #{desc => "await continue (ttest)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, ttest),
                           ok
                   end},
         #{desc => "start ttest (remote) client",
           cmd  => fun(#{domain          := local = Domain,
                         node            := Node,
                         mod             := Mod,
                         active          := Active,
                         msg_id          := MsgID,
                         max_outstanding := MaxOutstanding,
                         runtime         := RunTime,
                         server_path     := Path} = State) ->
                           Self   = self(),
                           Notify =
                               fun(Result) ->
                                       ?SEV_ANNOUNCE_READY(Self, ttest, Result)
                               end,                           
                           case ttest_tcp_client_start(Node, Notify,
                                                       Domain, Mod,
                                                       Path,
                                                       Active,
                                                       MsgID, MaxOutstanding,
                                                       RunTime) of
                               {ok, {Pid, _MRef}} ->
                                   {ok, State#{rclient => Pid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{domain          := Domain,
                         node            := Node,
                         mod             := Mod,
                         active          := Active,
                         msg_id          := MsgID,
                         max_outstanding := MaxOutstanding,
                         runtime         := RunTime,
                         server_addr     := Addr,
                         server_port     := Port} = State) ->
                           Self   = self(),
                           Notify =
                               fun(Result) ->
                                       ?SEV_ANNOUNCE_READY(Self, ttest, Result)
                               end,                           
                           case ttest_tcp_client_start(Node, Notify,
                                                       Domain, Mod,
                                                       {Addr, Port},
                                                       Active,
                                                       MsgID, MaxOutstanding,
                                                       RunTime) of
                               {ok, {Pid, _MRef}} ->
                                   {ok, State#{rclient => Pid}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "await ttest ready",
           cmd  => fun(#{tester  := Tester,
                         rclient := RClient} = State) ->
                           case ?SEV_AWAIT_READY(RClient, rclient, ttest, 
                                                 [{tester, Tester}]) of
                             {ok, Result} ->
                                 {ok, State#{result => Result}};
                             {error, _} = ERROR ->
                                 ERROR
                         end
                   end},
         #{desc => "await ttest (remote) client termination",
           cmd  => fun(#{rclient := RClient} = State) ->
                           ?SEV_AWAIT_TERMINATION(RClient),
                           State1 = maps:remove(rclient, State),
                           {ok, State1}
                   end},
         #{desc => "announce ready (ttest)",
           cmd  => fun(#{tester := Tester,
                         result := Result} = State) ->
                           ?SEV_ANNOUNCE_READY(Tester, ttest, Result),
                           {ok, maps:remove(result, State)}
                   end},


         %% *** Termination ***
         #{desc => "await terminate (from tester)",
           cmd  => fun(#{tester := Tester} = State) ->
                           case ?SEV_AWAIT_TERMINATE(Tester, tester) of
                               ok ->
                                   {ok, maps:remove(tester, State)};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "stop (client) node",
           cmd  => fun(#{node := Node} = _State) ->
                           stop_node(Node)
                   end},
         #{desc => "await (client) node termination",
           cmd  => fun(#{node := Node} = State) ->
                           receive
                               {nodedown, Node} ->
                                   {ok, maps:remove(node, State)}
                           end
                   end},


         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    TesterSeq =
        [
         %% *** Init part ***
         #{desc => "monitor server",
           cmd  => fun(#{server := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},
         #{desc => "monitor client",
           cmd  => fun(#{client := Pid} = _State) ->
                           _MRef = erlang:monitor(process, Pid),
                           ok
                   end},

         %% Start the server
         #{desc => "order server start",
           cmd  => fun(#{server := Pid} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid),
                           ok
                   end},
         #{desc => "await server ready (init)",
           cmd  => fun(#{domain := local,
                         server := Pid} = State) ->
                           {ok, Path} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_path => Path}};
                      (#{server := Pid} = State) ->
                           {ok, {Addr, Port}} =
                               ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{server_addr => Addr,
                                       server_port => Port}}
                   end},


         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{domain      := local,
                         client      := Pid,
                         server_path := Path} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Path),
                           ok;
                      (#{client      := Pid,
                         server_addr := Addr,
                         server_port := Port} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, {Addr, Port}),
                           ok
                   end},
         #{desc => "await client ready (init)",
           cmd  => fun(#{client := Client} = _State) ->
                           ok = ?SEV_AWAIT_READY(Client, client, init)
                   end},
 
         %% The actual test
         #{desc => "order client continue (ttest)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, ttest),
                           ok
                   end},
         #{desc => "await client ready (ttest)",
           cmd  => fun(#{server := Server,
                         client := Client} = State) ->
                           case ?SEV_AWAIT_READY(Client, client, ttest,
                                                 [{server, Server}]) of
                               {ok, Result} ->
                                   {ok, State#{result => Result}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},


         %% *** Terminate server ***
         #{desc => "order client terminate",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Client),
                           ok
                   end},
         #{desc => "await client down",
           cmd  => fun(#{client := Client} = State) ->
                           ?SEV_AWAIT_TERMINATION(Client),
                           State1 = maps:remove(client,    State),
                           {ok, State1}
                   end},
         #{desc => "order server terminate",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_TERMINATE(Server),
                           ok
                   end},
         #{desc => "await server down",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_TERMINATION(Server),
                           ok
                   end},

         
         %% Present the results
         #{desc => "present the results",
           cmd  => fun(#{result        := Result,
                         domain        := Domain,
                         server_mod    := ServerTrans,
                         server_active := ServerActive,
                         client_mod    := ClientTrans,
                         client_active := ClientActive,
                         msg_id        := MsgID} = State) ->
                           case Result of
                               #{status  := ok,
                                 runtime := RunTime,
                                 cnt     := Cnt,
                                 bcnt    := BCnt} ->
                                   ttest_report(Domain,
                                                ServerTrans, ServerActive,
                                                ClientTrans, ClientActive,
                                                MsgID,
                                                RunTime, BCnt, Cnt),
                                   ?SEV_IPRINT(
                                      "TTest results: "
                                      "~n   Run Time:                    ~s"
                                      "~n   Byte Count:                  ~s"
                                      "~n   Number of message exchanges: ~s"
                                      "~n~n",
                                      [
                                       ?TTEST_LIB:format_time(RunTime),
                                       if ((BCnt =:= 0) orelse (RunTime =:= 0)) ->
                                               ?TTEST_LIB:format("~w, ~w",
                                                                 [BCnt, RunTime]);
                                          true ->
                                               ?TTEST_LIB:format("~p => ~p byte / ms",
                                                                 [BCnt, BCnt div RunTime])
                                       end,
                                       if (RunTime =:= 0) ->
                                               "-";
                                          true ->
                                               ?TTEST_LIB:format("~p => ~p iterations / ms",
                                                                 [Cnt, Cnt div RunTime])
                                       end
                                      ]),
                                   {ok, maps:remove(result, State)};

                               #{status  := Failure,
                                 runtime := RunTime,
                                 sid     := SID,
                                 rid     := RID,
                                 scnt    := SCnt,
                                 rcnt    := RCnt,
                                 bcnt    := BCnt,
                                 num     := Num} ->
                                   ?SEV_EPRINT("Time Test failed: "
                                               "~n   ~p"
                                               "~n"
                                               "~nwhen"
                                               "~n"
                                               "~n   Run Time:       ~s"
                                               "~n   Send ID:        ~p"
                                               "~n   Recv ID:        ~p"
                                               "~n   Send Count:     ~p"
                                               "~n   Recv Count:     ~p"
                                               "~n   Byte Count:     ~p"
                                               "~n   Num Iterations: ~p",
                                               [Failure,
                                                ?TTEST_LIB:format_time(RunTime),
                                                SID, RID, SCnt, RCnt, BCnt, Num]),
                                   {error, Failure}
                           end
                   end},

         %% This is just so that the printout above shall have time to come
         %% out before then end of the test case.
         ?SEV_SLEEP(?SECS(1)),

         %% *** We are done ***
         ?SEV_FINISH_NORMAL
        ],

    i("start server evaluator"),
    ServerInitState = #{host   => local_host(),
                        domain => maps:get(domain,        InitState),
                        mod    => maps:get(server_mod,    InitState),
                        active => maps:get(server_active, InitState)},
    Server          = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator"),
    ClientInitState = #{host            => local_host(),
                        domain          => maps:get(domain,          InitState),
                        mod             => maps:get(client_mod,      InitState),
                        active          => maps:get(client_active,   InitState),
                        msg_id          => maps:get(msg_id,          InitState),
                        max_outstanding => maps:get(max_outstanding, InitState),
                        runtime         => maps:get(runtime,         InitState)},
    Client          = ?SEV_START("client", ClientSeq, ClientInitState),
    
    i("start 'tester' evaluator"),
    TesterInitState = #{domain => maps:get(domain, InitState),
                        server => Server#ev.pid,
                        client => Client#ev.pid},
    Tester = ?SEV_START("tester", TesterSeq, TesterInitState),

    i("await evaluator(s)"),
    ok = ?SEV_AWAIT_FINISH([Server, Client, Tester]).



ttest_tcp_server_start(Node, _Domain, gen, Active) ->
    Transport = socket_test_ttest_tcp_gen,
    socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active);
ttest_tcp_server_start(Node, Domain, sock, Active) ->
    TransportMod = socket_test_ttest_tcp_socket,
    Transport    = {TransportMod, #{domain => Domain,
                                    async  => true,
                                    method => plain}},
    socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active).

ttest_tcp_server_stop(Pid) ->
    socket_test_ttest_tcp_server:stop(Pid).

ttest_tcp_client_start(Node,
                       Notify,
                       _Domain, gen,
                       ServerInfo, Active, MsgID, MaxOutstanding, RunTime) ->
    Transport = socket_test_ttest_tcp_gen,
    socket_test_ttest_tcp_client:start_monitor(Node,
                                               Notify,
                                               Transport,
                                               ServerInfo,
                                               Active,
                                               MsgID, MaxOutstanding, RunTime);
ttest_tcp_client_start(Node,
                       Notify,
                       Domain, sock,
                       ServerInfo, Active, MsgID, MaxOutstanding, RunTime) ->
    TransportMod = socket_test_ttest_tcp_socket,
    Transport    = {TransportMod, #{domain => Domain,
                                    async  => true,
                                    method => plain}},
    socket_test_ttest_tcp_client:start_monitor(Node,
                                               Notify,
                                               Transport,
                                               ServerInfo,
                                               Active,
                                               MsgID, MaxOutstanding, RunTime).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-define(TTEST_MANAGER, esock_ttest_manager).

-record(ttest_report_id,
        {domain        :: socket:domain(),
         serv_trans    :: gen | sock,
         serv_active   :: once | boolean(),
         client_trans  :: gen | sock,
         client_active :: once | boolean(),
         msg_id        :: small | medium | large}).

-record(ttest_report, {id    :: #ttest_report_id{},
                       time  :: non_neg_integer(),
                       bytes :: non_neg_integer(),
                       msgs  :: non_neg_integer()}).

-spec ttest_report(Domain      :: socket:domain(),
                   ServTrans   :: gen | sock, ServActive   :: once | boolean(),
                   ClientTrans :: gen | sock, ClientActive :: once | boolean(),
                   MsgID       :: 1 | 2 | 3,
                   RunTime     :: non_neg_integer(),
                   NumBytes    :: non_neg_integer(),
                   NumMsgs     :: non_neg_integer()) -> ok.

ttest_report(Domain,
             ServTrans,   ServActive,
             ClientTrans, ClientActive,
             MsgID,
             RunTime,
             NumBytes,
             NumMsgs) ->
    ID = #ttest_report_id{domain        = Domain,
                          serv_trans    = ServTrans,
                          serv_active   = ServActive,
                          client_trans  = ClientTrans,
                          client_active = ClientActive,
                          msg_id        = ttest_msg_id_num_to_name(MsgID)},
    Report = #ttest_report{id    = ID,
                           time  = RunTime,
                           bytes = NumBytes,
                           msgs  = NumMsgs},
    %% If we run just one test case, the group init has never been run
    %% and therefor the ttest manager is not running (we also don't actually
    %% care about collecting reports in that case).
    (catch global:send(?TTEST_MANAGER, Report)),
    ok.

ttest_msg_id_num_to_name(1) ->
    small;
ttest_msg_id_num_to_name(2) ->
    medium;
ttest_msg_id_num_to_name(3) ->
    large.
    
ttest_manager_start() ->
    Self = self(),
    {Pid, MRef} = spawn_monitor(fun() -> ttest_manager_init(Self) end),
    receive
        {ttest_manager_started, Pid} ->
            erlang:demonitor(MRef, [flush]),
            ok;
        {'DOWN', MRef, process, Pid, Reason} ->
            exit({failed_starting, ttest_manager, Reason})
    after 5000 ->
            exit(Pid, kill),
            exit({failed_starting, ttest_manager, timeout})
    end.

ttest_manager_stop() ->
    case global:whereis_name(?TTEST_MANAGER) of
        Pid when is_pid(Pid) ->
            erlang:monitor(process, Pid),
            global:send(?TTEST_MANAGER, stop),
            receive
                {'DOWN', _MRef, process, Pid, _} ->
                    ok
            after 10000 ->
                    exit(Pid, kill),
                    ok
            end;
        _ ->
            ok
    end.

ttest_manager_init(Parent) ->
    yes = global:register_name(?TTEST_MANAGER, self()),
    ets:new(?TTEST_MANAGER, 
            [{keypos, #ttest_report.id}, named_table, protected, ordered_set]),
    Parent ! {ttest_manager_started, self()},
    ttest_manager_loop().

ttest_manager_loop() ->
    receive
        stop ->
            ?LOGGER:format("manager stopping~n", []),
            ttest_manager_done();

        #ttest_report{id    = _ID,
                      time  = _RunTime,
                      bytes = _NumBytes,
                      msgs  = _NumMsgs} = Report ->
            true = ets:insert_new(?TTEST_MANAGER, Report),
            ttest_manager_loop()
    end.

%% We are supposed to pretty print the result here...
ttest_manager_done() ->
    format_reports(inet),
    %% format_reports(inet6),
    ets:delete(?TTEST_MANAGER),
    exit(normal).

format_reports(Domain) ->
    ?LOGGER:format("Domain ~w reports:~n~n", [Domain]),
    format_reports(Domain, small),
    format_reports(Domain, medium),
    format_reports(Domain, large).
    
format_reports(Domain, MsgID) when is_atom(MsgID) ->
    case which_ttest_reports(Domain, MsgID) of
        [] ->
            ?LOGGER:format("   No ~w reports~n~n", [MsgID]);
        Reports ->
            ?LOGGER:format("   ~w reports: ~n", [MsgID]),
            lists:foreach(fun(R) -> format_report(R) end, Reports)
    end.

%% This should really be a table like this:
%%
%%             client
%% server      gen(false)  gen(once)  gen(true)  sock(false)  sock(once)  sock(true)
%% gen(false)  nnn
%% gen(once)   nnn
%% gen(true)   nnn
%% sock(false) nnn
%% sock(once)  nnn
%% sock(true)  nnn
%%
format_report(#ttest_report{id    = #ttest_report_id{serv_trans    = STrans,
                                                     serv_active   = SActive,
                                                     client_trans  = CTrans,
                                                     client_active = CActive},
                            time  = RunTime,
                            bytes = BCnt,
                            msgs  = MCnt}) ->
    ?LOGGER:format("      server ~w[~w] - client ~w[~w] => "
                   "~n         Run Time: ~s"
                   "~n         Bytes:    ~s"
                   "~n         Messages: ~s"
                   "~n", [STrans, SActive, CTrans, CActive,
                          ?TTEST_LIB:format_time(RunTime),
                          if ((BCnt =:= 0) orelse (RunTime =:= 0)) ->
                                  ?TTEST_LIB:format("~w, ~w",
                                                    [BCnt, RunTime]);
                             true ->
                                  ?TTEST_LIB:format("~p => ~p byte / ms",
                                                    [BCnt, BCnt div RunTime])
                          end,
                          if (RunTime =:= 0) ->
                                  "-";
                             true ->
                                  ?TTEST_LIB:format("~p => ~p iterations / ms",
                                                    [MCnt, MCnt div RunTime])
                          end]),
    ok.


which_ttest_reports(Domain, all) ->
    [R || R = #ttest_report{id = #ttest_report_id{domain = D}} <- 
              ets:tab2list(?TTEST_MANAGER), Domain =:= D];
which_ttest_reports(Domain, MsgID) ->
    [R || R = #ttest_report{id = #ttest_report_id{domain = D, msg_id = MID}} <- 
              ets:tab2list(?TTEST_MANAGER), (Domain =:= D) andalso (MsgID =:= MID)].



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% This mechanism has only one purpose: So that we are able to kill
%% the node-starter process if it takes to long. The node-starter
%% runs on the local node.
%% This crapola is hopefully temporary, but we have seen that on
%% some platforms the ct_slave:start simply hangs.
-define(NODE_START_TIMEOUT, 10000).
start_node(Host, NodeName) ->
    start_node(Host, NodeName, ?NODE_START_TIMEOUT).

start_node(Host, NodeName, Timeout) ->
    {NodeStarter, _} =
        spawn_monitor(fun() -> exit(start_unique_node(Host, NodeName)) end),
    receive
        {'DOWN', _, process, NodeStarter, Result} ->
            %% i("Node Starter (~p) reported: ~p", [NodeStarter, Result]),
            Result
    after Timeout ->
            exit(NodeStarter, kill),
            {error, {failed_starting_node, NodeName, timeout}}
    end.

start_unique_node(Host, NodeName) ->
    UniqueNodeName = f("~w_~w", [NodeName, erlang:system_time(millisecond)]),
    case do_start_node(Host, UniqueNodeName) of
        {ok, _} = OK ->
            global:sync(),
            %% i("Node ~p started: "
            %%    "~n   Nodes:        ~p"
            %%    "~n   Logger:       ~p"
            %%    "~n   Global Names: ~p",
            %%    [NodeName, nodes(),
            %%     global:whereis_name(socket_test_logger),
            %%     global:registered_names()]),
            OK;
        {error, Reason, _} ->
            {error, Reason}
    end.

do_start_node(Host, NodeName) when is_list(NodeName) ->
    do_start_node(Host, list_to_atom(NodeName));
do_start_node(Host, NodeName) when is_atom(NodeName) ->
    Dir   = filename:dirname(code:which(?MODULE)),
    Flags = "-pa " ++ Dir,
    Opts  = [{monitor_master, true}, {erl_flags, Flags}],
    ct_slave:start(Host, NodeName, Opts).


stop_node(Node) ->
    case ct_slave:stop(Node) of
        {ok, _} ->
            ok;
        {error, _} = ERROR ->
            ERROR
    end.

    

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

sock_open(Domain, Type, Proto) ->
    try socket:open(Domain, Type, Proto) of
        {ok, Socket} ->
            Socket;
        {error, Reason} ->
            ?FAIL({open, Reason})
    catch
        C:E:S ->
            ?FAIL({open, C, E, S})
    end.


sock_connect(Sock, SockAddr) ->
    try socket:connect(Sock, SockAddr) of
        ok ->
            ok;
        {error, Reason} ->
            ?FAIL({connect, Reason})
    catch
        C:E:S ->
            ?FAIL({connect, C, E, S})
    end.
    
sock_sockname(Sock) ->
    try socket:sockname(Sock) of
        {ok, SockAddr} ->
            SockAddr;
        {error, Reason} ->
            ?FAIL({sockname, Reason})
    catch
        C:E:S ->
            ?FAIL({sockname, C, E, S})
    end.
    

%% sock_listen(Sock) ->
%%     sock_listen2(fun() -> socket:listen(Sock) end).

%% sock_listen(Sock, BackLog) ->
%%     sock_listen2(fun() -> socket:listen(Sock, BackLog) end).

%% sock_listen2(Listen) ->
%%     try Listen() of
%%         ok ->
%%             ok;
%%         {error, Reason} ->
%%             ?FAIL({listen, Reason})
%%     catch
%%         C:E:S ->
%%             ?FAIL({listen, C, E, S})
%%     end.


%% sock_accept(LSock) ->
%%     try socket:accept(LSock) of
%%         {ok, Sock} ->
%%             Sock;
%%         {error, Reason} ->
%%             i("sock_accept -> error: ~p", [Reason]),
%%             ?FAIL({accept, Reason})
%%     catch
%%         C:E:S ->
%%             i("sock_accept -> failed: ~p, ~p, ~p", [C, E, S]),
%%             ?FAIL({accept, C, E, S})
%%     end.


sock_close(Sock) ->
    try socket:close(Sock) of
        ok ->
            ok;
        {error, Reason} ->
            i("sock_close -> error: ~p", [Reason]),
            ?FAIL({close, Reason})
    catch
        C:E:S ->
            i("sock_close -> failed: ~p, ~p, ~p", [C, E, S]),
            ?FAIL({close, C, E, S})
    end.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

local_host() ->
    try net_adm:localhost() of
        Host when is_list(Host) ->
	    %% Convert to shortname if long
	    case string:tokens(Host, [$.]) of
		[H|_] ->
		    list_to_atom(H)
	    end
    catch
        C:E:S ->
            erlang:raise(C, E, S)
    end.


%% The point of this is to "ensure" that paths from different test runs
%% don't clash.
mk_unique_path() ->
    [NodeName | _] = string:tokens(atom_to_list(node()), [$@]),
    Path = ?LIB:f("/tmp/esock_~s_~w", [NodeName, erlang:system_time(nanosecond)]),
    ensure_unique_path(Path).

ensure_unique_path(Path) ->
    case file:read_file_info(Path) of
        {ok, _} -> % Ouch, append a unique ID and try again
            ensure_unique_path(Path, 1);
        {error, _} ->
            %% We assume this means it does not exist yet...
            %% If we have several process in paralell trying to create
            %% (unique) path's, then we are in trouble. To *really* be
            %% on the safe side we should have a (central) path registry...
            Path
    end.

ensure_unique_path(Path, ID) when (ID < 100) -> % If this is not enough...
    NewPath = ?LIB:f("~s_~w", [Path, ID]),
    case file:read_file_info(NewPath) of
        {ok, _} -> % Ouch, this also existed, increment and try again
            ensure_unique_path(Path, ID + 1);
        {error, _} -> % We assume this means it does not exist yet...
            NewPath
    end;
ensure_unique_path(_, _) -> 
    skip("Could not create unique path").
    
            
which_local_socket_addr(local = Domain) ->
    #{family => Domain,
      path   => mk_unique_path()};

%% This gets the local address (not 127.0...)
%% We should really implement this using the (new) net module,
%% but until that gets the necessary functionality...
which_local_socket_addr(Domain) ->
    case which_local_host_info(Domain) of
        {ok, {_Name, _Flags, Addr}} ->
            #{family => Domain,
              addr   => Addr};
        {error, Reason} ->
            ?FAIL(Reason)
    end.


%% Returns the interface (name), flags and address (not 127...)
%% of the local host.
which_local_host_info(Domain) ->
    case inet:getifaddrs() of
        {ok, IFL} ->
            which_local_host_info(Domain, IFL);
        {error, _} = ERROR ->
            ERROR
    end.

which_local_host_info(_Domain, []) ->
    ?FAIL(no_address);
which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) ->
    which_local_host_info(Domain, IFL);
which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) ->
    which_local_host_info(Domain, IFL);
which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) ->
    which_local_host_info(Domain, IFL);
which_local_host_info(Domain, [{Name, IFO}|IFL]) ->
    case which_local_host_info2(Domain, IFO) of
        {ok, {Flags, Addr}} ->
            {ok, {Name, Flags, Addr}};
        {error, _} ->
            which_local_host_info(Domain, IFL)
    end;
which_local_host_info(Domain, [_|IFL]) ->
    which_local_host_info(Domain, IFL).

which_local_host_info2(Domain, IFO) ->
    case lists:keysearch(flags, 1, IFO) of
        {value, {flags, Flags}} ->
            which_local_host_info2(Domain, IFO, Flags);
        false ->
            {error, no_flags}
    end.

which_local_host_info2(_Domain, [], _Flags) ->
    {error, no_address};
which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags)
  when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) ->
    {ok, {Flags, Addr}};
which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags)
  when (size(Addr) =:= 8) andalso 
       (element(1, Addr) =/= 0) andalso
       (element(1, Addr) =/= 16#fe80) ->
    {ok, {Flags, Addr}};
which_local_host_info2(Domain, [_|IFO], Flags) ->
    which_local_host_info2(Domain, IFO, Flags).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Here are all the *general* test case condition functions.

%% We also need (be able) to figure out the the multicast address,
%% which we only support for some platforms (linux and sunos).
%% We don't do that here, but since we can only do that (find a
%% multicast address) for specific platforms, we check that we are
%% on of those platforms here.
has_ip_multicast_support() ->
    case os:type() of
        {unix, OsName} when (OsName =:= linux) orelse
                            (OsName =:= sunos) ->
            case which_local_host_info(inet) of
                {ok, {_Name, Flags, _Addr}} ->
                    case lists:member(multicast, Flags) of
                        true ->
                            ok;
                        false ->
                            not_supported(multicast)
                    end;
                {error, Reason} ->
                    not_supported({multicast, Reason})
            end;
        Type ->
            not_supported({multicast, Type})
    end.

has_ip_add_membership_support() ->
    has_socket_option_ip_support(add_membership).

has_ip_drop_membership_support() ->
    has_socket_option_ip_support(drop_membership).


has_socket_option_ip_support(Opt) ->
    has_socket_option_support(ip, Opt).

has_socket_option_support(Level, Option) ->
    case socket:supports(options, Level, Option) of
        true ->
            ok;
        false ->
            not_supported({options, Level, Option})
    end.




unix_domain_socket_host_cond() ->
    unix_domain_socket_host_cond(os:type(), os:version()).

unix_domain_socket_host_cond({unix, linux}, {M, _, _}) when (M < 3) ->
    skip("TC may not work on this version");
unix_domain_socket_host_cond(_, _) ->
    ok.

has_support_unix_domain_socket() ->
    case os:type() of
        {win32, _} ->
            skip("Not supported");
        _ ->
            case socket:supports(local) of
                true ->
                    ok;
                false ->
                    skip("Not supported")
            end
    end.


%% The idea is that this function shall test if the test host has 
%% support for IPv6. If not, there is no point in running IPv6 tests.
%% Currently we just skip.
has_support_ipv6() ->
    %% case socket:supports(ipv6) of
    %%     true ->
    %%         ok;
    %%     false ->
    %%         {error, not_supported}
    %% end.
    not_yet_implemented().



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

unlink_path(Path) ->
    unlink_path(Path, fun() -> ok end, fun() -> ok end).

unlink_path(Path, Success, Failure) when is_list(Path) andalso 
                                         is_function(Success, 0) andalso
                                         is_function(Failure, 0) ->
    ?SEV_IPRINT("try unlink path: "
                "~n   ~s", [Path]),
    case os:cmd("unlink " ++ Path) of
        "" ->
            ?SEV_IPRINT("path unlinked: "
                        "~n   Path: ~s", [Path]),
            Success();
        Result ->
            ?SEV_EPRINT("unlink maybe failed: "
                        "~n   Path: ~s"
                        "~n   Res:  ~s", [Path, Result]),
            Failure()
    end;
unlink_path(_, _, _) ->
    ok.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

not_supported(What) ->
    skip({not_supported, What}).

not_yet_implemented() ->
    skip("not yet implemented").

skip(Reason) ->
    throw({skip, Reason}).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

t() ->
    ts(ms).

ts(ms) ->
    erlang:monotonic_time(milli_seconds).

tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) ->
    T1 = A1*1000000000+B1*1000+(C1 div 1000), 
    T2 = A2*1000000000+B2*1000+(C2 div 1000), 
    T2 - T1.


formated_timestamp() ->
    format_timestamp(os:timestamp()).

format_timestamp({_N1, _N2, _N3} = TS) ->
    {_Date, Time}   = calendar:now_to_local_time(TS),
    %% {YYYY,MM,DD}   = Date,
    {Hour,Min,Sec} = Time,
    %% FormatTS = 
    %%     io_lib:format("~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~w",
    %%                   [YYYY, MM, DD, Hour, Min, Sec, N3]),  
    FormatTS = io_lib:format("~.2.0w:~.2.0w:~.2.0w", [Hour, Min, Sec]),  
    lists:flatten(FormatTS).

   
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

set_tc_name(N) when is_atom(N) ->
    set_tc_name(atom_to_list(N));
set_tc_name(N) when is_list(N) ->
    put(tc_name, N).

%% get_tc_name() ->
%%     get(tc_name).

tc_begin(TC) ->
    OldVal = process_flag(trap_exit, true),
    put(old_trap_exit, OldVal),
    set_tc_name(TC),
    tc_print("begin ***",
             "~n----------------------------------------------------~n", "").
    
tc_end(Result) when is_list(Result) ->
    OldVal = erase(old_trap_exit),
    process_flag(trap_exit, OldVal),
    tc_print("done: ~s", [Result], 
             "", "----------------------------------------------------~n~n"),
    ok.

%% *** tc_try/2,3 ***
%% Case:      Basically the test case name
%% TCCondFun: A fun that is evaluated before the actual test case
%%            The point of this is that it can performs checks to
%%            see if we shall run the test case at all.
%%            For instance, the test case may only work in specific
%%            conditions.
%% FCFun:     The test case fun
tc_try(Case, TCFun) ->
    TCCondFun = fun() -> ok end,
    tc_try(Case, TCCondFun, TCFun).

tc_try(Case, TCCondFun, TCFun) 
  when is_atom(Case) andalso
       is_function(TCCondFun, 0) andalso
       is_function(TCFun, 0) ->
    tc_begin(Case),
    try TCCondFun() of
        ok ->
            try 
                begin
                    TCFun(),
                    ?SLEEP(?SECS(1)),
                    tc_end("ok")
                end
            catch
                C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
                    %% i("catched[tc] (skip): "
                    %%   "~n   C:    ~p"
                    %%   "~n   SKIP: ~p"
                    %%   "~n", [C, SKIP]),
                    tc_end( f("skipping(catched,~w,tc)", [C]) ),
                    SKIP;
                C:E:S ->
                    %% i("catched[tc]: "
                    %%   "~n   C: ~p"
                    %%   "~n   E: ~p"
                    %%   "~n   S: ~p"
                    %%    "~n", [C, E, S]),
                    tc_end( f("failed(catched,~w,tc)", [C]) ),
                    erlang:raise(C, E, S)
            end;
        {skip, _} = SKIP ->
            tc_end("skipping(tc)"),
            SKIP;
        {error, Reason} ->
            tc_end("failed(tc)"),
            exit({tc_cond_failed, Reason})
    catch
        C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
            %% i("catched[cond] (skip): "
            %%   "~n   C:    ~p"
            %%   "~n   SKIP: ~p"
            %%   "~n", [C, SKIP]),
            tc_end( f("skipping(catched,~w,cond)", [C]) ),
            SKIP;
        C:E:S ->
            %% i("catched[cond]: "
            %%   "~n   C: ~p"
            %%   "~n   E: ~p"
            %%   "~n   S: ~p"
            %%   "~n", [C, E, S]),
            tc_end( f("failed(catched,~w,cond)", [C]) ),
            erlang:raise(C, E, S)
    end.


tc_print(F, Before, After) ->
    tc_print(F, [], Before, After).

tc_print(F, A, Before, After) ->
    Name = tc_which_name(),
    FStr = f("*** [~s][~s][~p] " ++ F ++ "~n", 
             [formated_timestamp(),Name,self()|A]),
    io:format(user, Before ++ FStr ++ After, []).

tc_which_name() ->
    case get(tc_name) of
        undefined ->
            case get(sname) of
                undefined ->
                    "";
                SName when is_list(SName) ->
                    SName
            end;
        Name when is_list(Name) ->
            Name
    end.
    
   
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

l2a(S) when is_list(S) ->
    list_to_atom(S).

l2b(L) when is_list(L) ->
    list_to_binary(L).

b2l(B) when is_binary(B) ->
    binary_to_list(B).

f(F, A) ->
    lists:flatten(io_lib:format(F, A)).

%% p(F) ->
%%     p(F, []).

%% p(F, A) ->
%%     p(F, A, "", "").

%% p(F, A, Before, After) when is_list(Before) andalso is_list(After) ->
%%     TcName = 
%%         case get(tc_name) of
%%             undefined ->
%%                 case get(sname) of
%%                     undefined ->
%%                         "";
%%                     SName when is_list(SName) ->
%%                         SName
%%                 end;
%%             Name when is_list(Name) ->
%%                 Name
%%         end,
%%     FStr = f("*** [~s][~s][~p] " ++ F ++ "~n", 
%%              [formated_timestamp(),TcName,self()|A]),
%%     i(Before ++ FStr ++ After, []).


%% d(F, A) ->
%%     d(get(dbg_fd), F, A).

%% d(undefined, F, A) ->
%%     [NodeNameStr|_] = string:split(atom_to_list(node()), [$@]),
%%     DbgFileName = f("~s-dbg.txt", [NodeNameStr]),
%%     case file:open(DbgFileName, [write]) of
%%         {ok, FD} ->
%%             put(dbg_fd, FD),
%%             d(FD, F, A);
%%         {error, Reason} ->
%%             exit({failed_open_dbg_file, Reason})
%%     end;
%% d(FD, F, A) ->
%%     io:format(FD, "~s~n", [f("[~s] " ++ F, [formated_timestamp()|A])]).

i(F) ->
    i(F, []).

i(F, A) ->
    FStr = f("[~s] " ++ F, [formated_timestamp()|A]),
    io:format(user, FStr ++ "~n", []),
    io:format(FStr, []).