aboutsummaryrefslogblamecommitdiffstats
path: root/erts/emulator/test/socket_SUITE.erl
blob: 4980ea2a82748c42abd98350e0eddbcd1b5fe0ff (plain) (tree)
1
2
3
4
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
14557
14558
14559
14560
14561
14562
14563
14564
14565
14566
14567
14568
14569
14570
14571
14572
14573
14574
14575
14576
14577
14578
14579
14580
14581
14582
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592
14593
14594
14595
14596
14597
14598
14599
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619
14620
14621
14622
14623
14624
14625
14626
14627
14628
14629
14630
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649
14650
14651
14652
14653
14654
14655
14656
14657
14658
14659
14660
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672
14673
14674
14675
14676
14677
14678
14679
14680
14681
14682
14683
14684
14685
14686
14687
14688
14689
14690
14691
14692
14693
14694
14695
14696
14697
14698
14699
14700
14701
14702
14703
14704
14705
14706
14707
14708
14709
14710
14711
14712
14713
14714
14715
14716
14717
14718
14719
14720
14721
14722
14723
14724
14725
14726
14727
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738
14739
14740
14741
14742
14743
14744
14745
14746
14747
14748
14749
14750
14751
14752
14753
14754
14755
14756
14757
14758
14759
14760
14761
14762
14763
14764
14765
14766
14767
14768
14769
14770
14771
14772
14773
14774
14775
14776
14777
14778
14779
14780
14781
14782
14783
14784
14785
14786
14787
14788
14789
14790
14791
14792
14793
14794
14795
14796
14797
14798
14799
14800
14801
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812
14813
14814
14815
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826
14827
14828
14829
14830
14831
14832
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889
14890
14891
14892
14893
14894
14895
14896
14897
14898
14899
14900
14901
14902
14903
14904
14905
14906
14907
14908
14909
14910
14911
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921
14922
14923
14924
14925
14926
14927
14928
14929
14930
14931
14932
14933
14934
14935
14936
14937
14938
14939
14940
14941
14942
14943
14944
14945
14946
14947
14948
16392
16393
16394
16395
16396
16397
16398
16399
16400
16401
16402
16403
16404
16405
16406
16407
16408
16409
16410
16411
16412
16413
16414
16415
16416
16417
16418
16419
16420
16421
16422
16423
16424
16425
16426
16427
16428
16429
16430
16431
16432
16433
16434
16435
16436
16437
16438
16439
16440
16441
16442
16443
16444
16445
16446
16447
16448
16449
16450
16451
16452
16453
16454
16455
16456
16457
16458
16459
16460
16461
16462
16463
16464
16465
16466
16467
16468
16469
16470
16471
16472
16473
16474
16475
16476
16477
16478
16479
16480
16481
16482
16483
16484
16485
16486
16487
16488
16489
16490
16491
16492
16493
16494
16495
16496
16497
16498
16499
16500
16501
16502
16503
16504
16505
16506
16507
16508
16509
16510
16511
16512
16513
16514
16515
16516
16517
16518
16519
16520
16521
16522
16523
16524
16525
16526
16527
16528
16529
16530
16531
16532
16533
16534
16535
16536
16537
16538
16539
16540
16541
16542
16543
16544
16545
16546
16547
16548
16549
16550
16551
16552
16553
16554
16555
16556
16557
16558
16559
16560
16561
16562
16563
16564
16565
16566
16567
16568
16569
16570
16571
16572
16573
16574
16575
16576
16577
16578
16579
16580
16581
16582
16583
16584
16585
16586
16587
16588
16589
16590
16591
16592
16593
16594
16595
16596
16597
16598
16599
16600
16601
16602
16603
16604
16605
16606
16607
16608
16609
16610
16611
16612
16613
16614
16615
16616
16617
16618
16619
16620
16621
16622
16623
16624
16625
16626
16627
16628
16629
16630
16631
16632
16633
16634
16635
16636
16637
16638
16639
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650
16651
16652
16653
16654
16655
16656
16657
16658
16659
16660
16661
16662
16663
16664
16665
16666
16667
16668
16669
16670
16671
16672
16673
16674
16675
16676
16677
16678
16679
16680
16681
16682
16683
16684
16685
16686
16687
16688
16689
16690
16691
16692
16693
16694
16695
16696
16697
16698
16699
16700
16701
16702
16703
16704
16705
16706
16707
16708
16709
16710
16711
16712
16713
16714
16715
16716
16717
16718
16719
16720
16721
16722
16723
16724
16725
16726
16727
16728
16729
16730
16731
16732
16733
16734
16735
16738
16739
16740
16741
16742
16743
16744
16745
16746
16747
16748
16749
16750
16751
16752
16753
16754
16755
16756
16757
16758
16759
16760
16761
16762
16763
16764
16765
16766
16767
16768
16769
16770
16771
16772
16773
16774
16775
16776
16777
16778
16779
16780
16781
16782
16783
16784
16785
16786
16787
16788
16789
16790
16791
16792
16793
16794
16795
16796
16797
16798
16799
16800
16801
16802
16803
16804
16805
16806
16807
16808
16809
16810
16811
16812
16813
16814
16815
16816
16817
16818
16819
16820
16821
16822
16823
16824
16825
16826
16827
16828
16829
16830
16831
16832
16833
16834
16835
16836
16837
16838
16839
16840
16841
16842
16843
16844
16845
16846
16847
16848
16849
16850
16851
16852
16853
16854
16855
16856
16857
16858
16859
16860
16861
16862
16863
16864
16865
16866
16867
16868
16869
16870
16871
16872
16873
16874
16875
16876
16877
16878
16879
16880
16881
16882
16883
16884
16885
16886
16887
16888
16889
16890
16891
16892
16893
16894
16895
16896
16897
16898
16899
16900
16901
16902
16903
16904
16905
16906
16907
16908
16909
16910
16911
16912
16913
16914
16915
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950
16951
16952
16953
16954
16955
16956
16957
16958
16959
16960
16961
16962
16963
16964
16965
16966
16967
16968
16969
16970
16971
16972
16973
16974
16975
16976
16977
16978
16979
16980
16981
16982
16983
16984
16985
16986
16987
16988
16989
16990
16991
16992
16993
16994
16995
16996
16997
16998
16999
17000
17001
17002
17003
17004
17005
17006
17007
17008
17009
17010
17011
17012
17013
17014
17015
17016
17017
17018
17019
17020
17021
17022
17023
17024
17025
17026
17027
17028
17029
17030
17031
17032
17033
17034
17035
17036
17037
17038
17039
17040
17041
17042
17043
17044
17045
17046
17047
17048
17049
17050
17051
17052
17053
17054
17055
17056
17057
17058
17059
17060
17061
17062
17063
17064
17065
17066
17067
17068
17069
17070
17071
17072
17073
17074
17075
17076
17077
17078
17079
17080
17081
17082
17083
17084
17085
17086
17087
17088
17089
17090
17091
17092
17093
17094
17095
17096
17097
17098
17099
17100
17101
17102
17103
17104
17105
17106
17107
17108
17109
17110
17111
17112
17113
17114
17115
17116
17117
17118
17119
17120
17121
17122
17123
17124
17125
17126
17127
17128
17129
17130
17131
17132
17133
17134
17135
17136
17137
17138
17139
17140
17141
17142
17143
17144
17145
17146
17147
17148
17149
17150
17151
17152
17153
17154
17155
17156
17157
17158
17159
17160
17161
17162
17163
17164
17165
17166
17167
17168
17169
17170
17171
17172
17173
17174
17175
17176
17177
17178
17179
17180
17181
17182
17183
17184
17185
17186
17187
17188
17189
17190
17191
17192
17193
17194
17195
17196
17197
17198
17199
17200
17201
17413
17414
17415
17416
17417
17418
17419
17420
17421
17422
17423
17424
17425
17426
17427
17428
17429
17430
17431
17432
17433
17434
17435
17436
17437
17438
17439
17440
17441
17442
17443
17444
17445
17446
17447
17448
17449
17450
17451
17452
17453
17454
17455
17456
17457
17458
17459
17460
17461
17462
17463
17464
17465
17466
17467
17468
17469
17470
17471
17472
17473
17474
17475
17476
17477
17478
17479
17480
17481
17482
17483
17484
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495
17496
17497
17498
17499
17500
17501
17502
17503
17504
17505
17506
17507
17508
17509
17510
17511
17512
17513
17514
17515
17516
17517
17518
17519
17520
17521
17522
17523
17524
17525
17526
17527
17528
17529
17530
17531
17532
17533
17534
17535
17536
17537
17538
17539
17540
17541
17542
17543
17544
17545
17546
17547
17548
17549
17550
17551
17552
17553
17554
17555
17556
17557
17558
17559
17560
17561
17562
17563
17564
17565
17566
17567
17568
17569
17570
17571
17572
17573
17574
17575
17576
17577
17578
17579
17580
17581
17582
17583
17584
17585
17586
17587
17588
17589
17590
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610
17611
17612
17613
17614
17615
17616
17617
17618
17619
17620
17621
17622
17623
17624
17625
17626
17627
17628
17629
17630
17631
17632
17633
17634
17635
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645
17646
17647
17648
17649
17650
17651
17652
17653
17654
17655
17656
17657
17658
17659
17660
17661
17662
17663
17664
17665
17666
17667
17668
17669
17670
17671
17672
17673
17674
17675
17676
17677
17678
17679
17680
17681
17682
17683
17684
17685
17686
17687
17688
17689
17690
17691
17692
17693
17694
17695
17696
17697
17698
17699
17700
17701
17702
17703
17704
17705
17706
17707
17708
17709
17710
17711
17712
17713
17714
17715
17716
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726
17727
17728
17729
17730
17731
17732
17733
17734
17735
17736
17737
17738
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748
17749
17750
17751
17752
17753
17754
17755
17756
17757
17758
17759
17760
17761
17762
17763
17764
17765
17766
17767
17768
17769
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789
17790
17791
17792
17793
17794
17795
17796
17797
17798
17799
17800
17801
17802
17803
17804
17805
17806
17807
17808
17809
17810
17811
17812
17813
17814
17815
17816
17817
17818
17819
17820
17821
17822
17823
17824
17825
17826
17827
17828
17829
17830
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847
17848


                   
                                                        















                                                                           









                                                                         



                                                          


                                                              
                                           








                                                   
                              
                                           





                                                         
 



                                                 
                                      


                                    
                                              
                                              
                                                   


             


                            
                             

                                     

                                     
                                          
                                          
                                          
                                          
                                    
                                    
                                          
                                          
 
                             
                              
                              
                                          
                                          
                                          
                                          
                                    
                                    
                                          
                                          
                                      
                                      
                                     
                                     
                                    
                                    
                                  
                                  
                                     
                                     
                                       
                                       
                                      
                                      
                                     
                                     
                                   
                                   
                                      
                                      
 
 
                               
                                      
                                            
                                                  

                                       
                                     
                                     
                                  
                              
                               
                                  
                              
                                  
                               
                                          
 
                                         



                               

                               

                            

                              










                                

                               
                                  

                                      
                                      

                                      
                                      
 

                                    
                                    

                                        
                                        

                                       
                                       

                                       
                                       

                                        
                                        
 

                                    
                                    
                                       
                                       
                                       
 

                                                 
                                                 

                                                    
                                                    
 
                           
                                               
                                               
                                               
                                                     
                                                     

                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
 
                                             
                                             
                                             
 

                                                      
                                                      

                                                       
                                                       
                                                      
                                                      
                                                      


                                                            
                                                            

                                                             
                                                             


                                                            
                                                            

                                                             
                                                             
                                                            
                                                            
                                                            
 

                                                            
                                                            
                                                             
                                                             
                                                             
 


                                                       
                                        




                                         
 





                                         
 




                                         
                                        


                                                       


















                                          
                                         


                                                      


















                                         
                                        


                                                      


















                                          
                                         


                                                      


















                                         
                                        


                                                      


















                                          
                                         


                                                           


















                                          
                                         


                                                           

                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           
                                          
                                          
                                          


                                                          


















                                          
                                         


                                                          

                                          
                                          
                                           
                                           


                                           
                                          


                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           
                                          
                                          
                                          


                                                          


















                                          
                                         


                                                          

                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           

                                          
                                          


                                          
                                          

                                           
                                           
                                          

                                          
 


                   
 


                   
 

                                                                         


                                           
 

                                   
 

                                               
 
                                               
 





                                      
 
 



                                                                       


                               
 

                                   
 






                                                                         



                                                                


















                                                                        

            








                                                                           



                                                                   


































































                                                                           
 
                                                 



              
                       
                        
                        
                          
                                 

      




                   
                    

                               
                               

                               
                                    
                                    
                                    
                                    
                              
                              

                                    

      

                    
                        
                        
                                    
                                    
                                    
                                    
                              
                              
                                    
                                    
                                
                                
                               
                               
                              
                              
                            
                            
                               
                               
                                 
                                 
                                
                                
                               
                               
                             


                                

      

                      
                              
                                 
                               



                                  



                          
                                
                                      
                                           

      

                             
                                         
                               
                               
                            
                        
                         
                            


                            

      





                                     




                                   



                              
                              
     



                         

                         

                      

                        











                          

      

                                                                     
                       
     
                                
                             

                                
      
 
                                                                         
                                                     



                                
                                
                                

                                

      




                                                                    
                              
 

                                  
                                  
 

                                 
                                 

                                 
                                 

                                  

                                  






                                                                     
                              

                                 

                                 

      





                                                                             
                                           

                                              

                                              

      
 

                  
                               





                                         


                                         
                                         
                                         
                                               
                                               
                                               
                                               
                                               

                                               
                                               
                                              

      

                         
                                       
                                       

                                      
 

                               

                                                
                                                

                                                 
                                                 
                                                
                                                

                                               
 

                                     

                                                      
                                                      

                                                       

                                                      
 

                                     

                                                      
                                                      

                                                       
                                                       
                                                      
                                                      
                                                      


                                                      
                                                      
                                                       

                                                       
      
    

                
                                                   
                          

                                                  
                          

                                                  
                          

                                                       
                           

                                                      
                           

                                                      
                          
 



                                              






                                              











                                              
                                  





                                   

                                 
 



                                              

                                  
 

                                   
 
                                  

                                 
 



                                              







                                   

      











































                                              
 
                                             






                                             

















































                                              












































                                             
                                             






                                             

















































                                              












































                                             
                                                  






                                                  

















































                                                  














                                                  
                                    


                                     
                                     

                                    

                                    







                                                  
                                    


                                     
                                     

                                    

                                    







                                                  
                                    


                                     
                                     

                                    

                                    

      
                                                 






                                                 

















































                                                 














                                                  
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    

      
                                                 






                                                 

















































                                                 














                                                  
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    







                                                 
                                    


                                     
                                     

                                    

                                    

      






                                                                         
                         
















                                                              
        

                   
                           

       




                                                
                          



                                                                
                                                                            







                                                
                         




                                                         
                                 


                                                   





                                   


                                
                      


           











                                                        
 
                
                                                                         

                                                                         

















                                                                         
                                          



                                     







                                                                                    
                                                            





                                              

                                                  







                                                                     




                                                  
















                                            
 


                                                                         





                                                                         
 






                                                                
                  






                                                       










                                                                         
                  






                                                       



                                                                         








                                                                       
                                                         


















                                                                         
                                                         









                                                                         















































                                                                           






                                                                               

                                       




                                                                            




























                                                                               
                              

                                                  


                               
                           


                                                     

 
 








                                                                         
                  








                                                                 









                                                                         
                       






                                                                



                                                    








                                                                 



                                                          

 

                                                                         






                                                                
                  


                                                  

                                                                  



                                                                        


                                                                 


                                                              
                                                                          
                                                                           


                                                                 
                                                                                    





                                                               
                                               



                                                          

 

                                                                         








                                                                



                                                    


































                                                                                    
                                     


                                   





                                                                    
                                                                 

                                                       
                        
 
                                     



                                                                  

                              
                                                              







                                                                                



                                                       

                                                           

                                                        
 
                                     


                                                                  


                                                         
                                                              







                                                                                



                                                       

                                                           



                                                                           
                                                      

                                         
                                                                           









                                                                          


                                                                           
                                                      


                                                                           









                                                                          

                                      

                                           
                                                                 
                                                   
                                   


                                                                                    



                                                               

                                      

                                           
                                                                 
                                                   
                                   


                                                                                    



                                                               


                               
                           
          

                                                     











                                                                          
                   








                                                         









                                                                          
                                           






                                                          
                                                         







                                                         
                                                   



                                                          

 

                                                                         






                                                                           
                   















                                                                 
                                               



                                                          

 

                                                                         
                                                                           
                                           






                                                                
                                                         






                                                              






                                                                         

                                                                         



                                                               

                                                           



                                                               



                                                 








                                                                         
                                     
                                  

                


                                               
                                                       








                                                                   

                                                      
                                                                 


                                                   
                                          
                                                     
                                                                     






                                                               









                                                                                

                                                          
                                                                            








                                                               
                                           





                                                                              
                                                                   

                             



                                              
                                                                      
                        



                                                       
                                                                            
                                                               



                                                    

                                              
                                                               



                                                         






                                                    

                                                   
                                                                 



                                                      
                                                                          
                        
                                
                                                         

                                                 

                                                 
                                                                   

                             



                                                      
                                                                       






                                                                    
                                                   
                                                   
                                                          

                                         




                                                                 




                                                                               







                                                                   
                        

                               
                           



                

                                               



                                                                               
                                                               








                                                                              
                                                  







                                                                           
                                                                          

                                   
                                          
                                                     
                                                                     






                                                              
                                                                    
                                                         

                                             



                                                    

                                              
                                                             





                                                       
                                                                       
                        
                                       
                                                            

                                                    

                                              
                                                                



                                                       
                                                                        
                        



                                                        

                                                   
                                                                 


                                                    



                                                         

                                                 
                                                                   





                                                      
                                                                       





                                                                    
                                  

                                           
                                                                 
                                                   
                                   




                                                                               



                                                           
                        

                               
                           


















                                                                
                                                    



                                                   
                                                                            





                                                                         
                                                          



                                                    
                                                                   




                                                            
                                                                  

                             
                              

                                                             
                                                                   



                                                       
                                                                    


                                                       
                                                                   


                                                                  
                                                                    



                                                            
                                                                     


                                                       
                                                                     


                                                                
                                                                      



                                                          
                                                                       


                                                       
                                                                       





                                                       
                                                           



                                                      
                                                          




                                                               
                                                           



                                                      
                                                          




                                                               
                           

          
                                
                                                        
 
                                
                                                        
                            



                                                 
                                                              
 
                                                     



                                                                         
 
                                                                   








                                                    

















                                                                         




                                                                         


















                                                                         


















                                                                   
                                                                 


















































                                                                            




































                                                                          









































                                                                              

                                                                 




































                                                                             



                                                                             





































                                                                                






















                                                                            



































                                                                          



























































































                                                                            






































                                                                     















































                                                                         























                                                                      





                                                                         












                                                                      
                                           
















                                                                         


                                                                      

                                                              





















                                                                      

                                                             







                                                           





                                                                         












                                                                      
                                           





























                                                                         

















                                                                   
                                                                 































                                                                             
                                                                   

                                                                



                                                                               


                                                                      
                                                                   













                                                                    


                                                                            






                                                               
                                                 







                                                                
                                                   
                                              
                                                                 

                             
 
























































                                                                           
                                                                 









                                                                





                                                        



























                                                                             
                                                                       
























                                                                        
                                               







                                                          
                                                 
                                              
                                                                 
























































































                                                                                
                                                       
                                                    
                                                                       























                                                                          
                                                     
                                                    
                                                                       

























































                                                                         





                                                                          
                                   





                                                          
                                    
















                                                                         












                                                                          
                                           
















                                                                         






















                                                                           
                                                     
                                             

                                                             
                                                           









                                                          















                                                                           
                                           

























                                                                      

                                                                         


















                                                                   
                                                                 





































                                                                      
                                                                   



















































                                                                           
                                                                   

































































































                                                                              

                                                                 

























































                                                                          
                                                                   


















































































































































































































                                                                            





                                                              
                            






                                                                         

                                                                  
                                       





                                                            
                   





                                                                          

                                                             












                                                                         









                                                                  
                                           



















                                                                          
                                                                 
                                       





                                                           
                   





                                                                      

                                                             












                                                                         









                                                                 
                                           



















                                                                         

















                                                                   
                                                                 


































                                                                             
                                                      



















































































































































                                                                                
 
                                                                
                                       












                                                                       

                                                               













                                                                         









                                                                
                                           




















                                                                         


















                                                                   
                                                                 





































                                                                      
                                                                            









































































































































                                                                                  


                                                                         
                                       




















                                                                         









                                                              
                                           












                                                                         
                                                                 
                                       




















                                                                         









                                                                 
                                           












                                                                         


















                                                                   
                                                                 
























































                                                                      
                                                                            



















































































                                                                                

                                                                 
























































































































































































                                                                            

                                                                         
                                                                          
                                                              
                                                                      











                                                                          
                                             

                                                             












                                                                         










                                                                          
                                           



















                                                                          
                                                                         
                                                              
                                                                      











                                                                      
                                             

                                                             












                                                                         










                                                                         
                                           



















                                                                         

















                                                                   
                                                                 

































                                                                    
                                                      













                                                                                
                                                                               





                                                                         
                                                                            























































                                                                           
                                                      













                                                                                
                                                                               





                                                                         
                                                                            













                                                                       
                                                              






















                                                                                  









                                                                























































































                                                                               































                                                                            



































                                                                       











                                                                         
                                                                      












                                                                       

                                                               













                                                                         










                                                                        
                                           




















                                                                         


















                                                                   
                                                                 





































                                                                      
                                                                            
















                                                                                  
                                                                                 





                                                                         
                                                                            







                                                              
 









                                                                       
 































                                                                        
                                                      













                                                                                  
                                                                                 





                                                                         
                                                                            








































































































































































































                                                                                    


 

                                                                         


                                                                      
                                                                      




















                                                                         










                                                                      
                                           












                                                                         

                                                                         
                                                                      














                                                              
















                                                                         
                                           






                                                              
























                                                                         
                                                                 
























































                                                                      
                                                                            
















                                                                                
                                                                               




























































                                                                         
                                                      













                                                                                
                                                                               





                                                                         
                                                                            












































                                                                                  

                                                                 




































































































































































































































































































                                                                               







                                                                         
 





                                                                     
                  

                                                      
 
                               






                                                 

































                                                                          





                                                                        



























                                                                      


                                                                                






                                                                     








                                                                                                  





                                                                     









                                                                                























































































































































                                                                               
                                      
                                                                    
                                                        
                             
                                      
 
                                  
                                                                   
                                                        
                             
                                      



                                                                         




































                                                                   
                                                                 



















































































































































































































































                                                                                  
                                                                 




































































































































































































































































































































































































                                                                                   





                                                                        
                   

                                                                  
 
                                           






                                                 




                                 
                                                               






                                                                   
                        

                                   





















                                                                            
                                                
                                                       
                                                                  

                             
                                            
                                                       
                                                                     



























                                                                            
                                            
                                                       
                                                              
                             
 
                        

                               

                                                      
                                                                


                                                               


                               
                           











                                                                    






                                                                   













                                                                     
                                                             

                             
                                                      
                                                       
                                                                      


























                                                                            
                                                     
                                                       
                                                                 



                                                       
                                                                   
                             












                                                                  

                               

                                                       
                                                           

                             
                                              
                                                      
                                                          
                                                           







                                                         
                           

          
                                             
                           


                                                                    


                                             
                                                     
                                                                    
 



                                               
                           


                                                                    


                                            
                                                     



                                                                    
 


                                                                         
 

                                              
 
                                     
       
                                   
       
                                                             
                   
                                       
                   
                                                
               
                                                       


 
                                














                                                                 
                                   








                                                                  

                                                       








                                                                              



                                                                            
                                                                       
                                                              
                                                  
                                                         

                                                                        


                                        

                                                       

                                                  

                                                                      







                                                                         

                                                                    









                                                         

                                                      









                                                                              

                                                                        


                                        

                                                      

                                                  

                                                                      







                                                                         


                                                  



                                                         












                                                        
 





































                                                                         








                                                                   
                                                              









                                                                              




                                                                       
                                                         

                                                                        


                                        
                                                              













                                                                                 
                                                         








                                                                                 
                                                             














                                                                                   
                                                             













                                                                                 
                                                           








                                                      
                                                               














                                                                                   
                                                               













                                                                                 
                                                








                                                                   
                                                             










                                                                      
                                                                     














                                                                                   
                                                                     

































                                                                                 
                                                                    














                                                                                   
                                                                    











                                                                                 
                                                   














                                                                                   
                                                   











                                                                                 
                                                                














                                                                                   
                                                                












                                                                                 
                                                





                                                                              
                                         









                                                          












                                                                         















                                                                         










                                                           
                                                        















                                                      
                                                                     
                                                                     






















































                                                                              



                                                                                
                                                         

                                                                        







































                                                                                   
                                                                



                                                                   



                                                                                 
















                                                                                   

                                                                



                                                                   






                                                                                 



















                                                                                   



                                                                   




















                                                                                   



                                                                   
























                                                                                   



                                                                   








                                                           



                                                                   












                                                           












                                                                         



































































                                                                               




                                                                             






                                                                        
                                                  




                                                                      
                                                               



                                                    
















































































































                                                                                       
                                                              

                                                    
                                            
                                                                   
                                                                    
                                      
                                             
                                                                            

                                                                        









                                                                        
                                                  













                                                                         
                                                         


                                        
                                         
                                                  

                                                                      
                                                   




                                                                   









                                                                            


























                                                                              
                                                                




                                                                   



                                                                               














































                                                                         
                                 



                                                                       


































































                                                                         


                                                                  

                                                                   
                                                                   








                                                                        
                                                   
                                                                   









                                                                        

























                                                                         
                                  
                                                                   



















































































































                                                                         


                                                                    
                                                                

                                                                  


                                                                  









































































                                                                               



                                                                      











































                                                                         















                                                                         































































































































                                                                               















                                                                         


















                                                                         


                                                    



























                                                                     
                                                                 


























































































































































































                                                                               
                  
                               































                                                              
                                                             







                                                                      
                                             





















                                                                              
        















                                                                   
                                              
                                







                                                                         







                                                                         
 

                                                                
                             
       
                           
       
                                                     
                   
                                              
                               
                
                   



                                                       

                                                     
 







                                                             


                                            

























                                                                     




                                                                         
                             
       
                           
       
                                                     
                   
                               
                                                                  
                   



                                                        

                                                     


                                                                         




                                                                       
 
                                
                                  





                                               


                                                                  




                                                                   




                                                      
                                                                 
                                                        










                                                                   
                                                                     







                                                               

                                                                
                        
                                           
                                                             
                                                                   

                             


                                     
                                                      
                                                                       



                                                                    

                              






                                                               

                               
                           

          
               
         









                                                                   

                             

                             

                                                      
                                                                 
                                                        
                        

                                                  
                                                                        




                                                                        

                                                 

                              



                                                                  
                        





































                                                                             



                                                    














                                                                           



                                                                            

                                              



                                                    














                                                                             



                                                    





















                                                                         


                              


















                                                                   
                                                                 

                                                        
                                        


                                                                

                             

                                                                       
                                                                               

                                                              
                        










                                                                  
 









                                                                       
                        




                                                                         
                                    



                                                    

                        

                                    











                                                                  
                                                       
                                                           

                             
                                       
                                                      
                                                          


                                                                   
                        

                               
                           

          
                                 
                                                               
                                                                       
 




                                                                       
                                 

                                                          
                                                                       
 
                            
                                                     

 

                                 
                                                 

                            

                                    




                                                                              
                                        
                                                               
                                                        

                 

                                  

                                             




                                                    
 














                                                            
 







                                                        
 
                                                                   
                                          

































                                                                              
 
                                                                

                                            

                                              
                           
                        
                                 

                                
                                               

                       

                                                          
                

                                        
               
                          
                                       
                                     
             
                      
        






                                                  




                                                                         
                            
       
                          
       
                                                    
                   

                              

                                                                  
                





                                                                         
                            
       
                          
       
                                                    
                   
                              
                                           
                   

                                                                   
                



                                                                         





                                                      
                                                                 








































                                                                                  
                                                 















                                                                           
                           

          
                                 
                                                        
 
                         
                                     




                                                                         







                                                                     
                   















                                                                         
                   
                               
                                           
                   












                                                                         
                                                       





                                                                


                                                      
                                                                 























                                                                   
                                           
                                                              
                                                                    

                             


                                             
                                                       
                                                                      
                        






                                                                             

                                                                            







                                                                                  
                                                 






                                                                           
                                             
                                              
                                                               

                             

                             

                                                       
                                                                
                             
                        



                                                    
                                                          


                               
                           







                                 
                                                                


                                                        
                        


                                                                

                             
                                           
                                                       
                                                             
                             


                                        

                                                       
                                                                      
                        













                                                                             
                                                                                 
                                                 

                                               


                                                                       



                                                                           
                                             
                                                       
                                                               

                             

                             
                                     
                                                      
                                                                       



                                                                    



                               
                           

























                                                                
                                                    

                             
                                                      
                                                          
                                                                                   
                                                      




                                                                           
                                                           

                             
                                                       
                                                           
                                                                     




                                                                           
                                                           

                             
                                                       
                                                           
                                                                     




                                                           
                                                               



                                                           
                                                               



                                                           
                                                               



                                         
                                                        
                                                           
                                                                       
                        
                                                         
                                                           
                                                                       
                        
                                                         
                                                           
                                                                       

                        
                     

                                                           
                                                        

                             

                                                          






                                                                              
                        

                                                           
                                                        

                             

                                                          






                                                                              
                        

                                                           
                                                        

                             

                                                          






                                                                              


                               
                           

          
                                        
                               
                                                                                
 
                                         
                                                    
                                                                                
    
                                         
                                    
                                                                                
 
                                 


                                                              
                                                              
 
                            
                                                                               




                                                                         

                                                             
                          
       
                        
       
                                                  




                                                





                                                                         
                          
       
                        
       
                                                  
                            
                                           



                                                 





                                                                         
                            
       
                          
       





                                                     





                                                                         
                            
       
                          
       

                                                    
                                           



                                                      





                                                                         
                             
       
                           
       
                                                     




                                                   





                                                                         
                             
       
                           
       
                                                     
                               
                                           



                                                    






                                                                         
                          
       
                        
       
                                                  




                                               






                                                                         
                          
       
                        
       
                                                  
                            
                                           



                                                 





                                                                         
                          
       
                        
       
                                                  
                   

                            


                                                                        
                                                  

                                                     





                                                                         
                          
       
                        
       
                                                  
                   
                            
                                           
                   

                                                

                                                                  
                                      

                                                          
                                                          




                                                              



                                                                         
                                
                                  





                                               
                                                       
                                                         
                        




                                                                   



                                                      
                                                                 
                                                        










                                                                   
                                                                     










                                                               
                                           
                                                             
                                                                   

                             

                                   
                                                      
                                              
                                                                           
                        
                                    








                                                              


                                                                               
                                                  
                                                                             





                                                               
                                           
                                                                                 
                                                 

                                               


                                                                       



                                                                           

                                                           
                                                                    





                                                      
                                                                       



                                                                    













                                                          
                           






                                               
                                                               

                                                             
                        




                                                                   



                                                                           

                                                                 
                                                                          










                                                                   
                                                                    






                                                         
                                           
                                                       
                                                             





                                                       
                                                                       

                             
                                                            






                                                      
                                                                       



                                                                    








                                                         
                           





                                    


                                                                   

                                    


                                                                   




                                                       
                                                       



                                                      
                                                                               
                                                            


                                                            
                                                                       





                                                                            
                                                             

                             
                                               
                                                       
                                                                 




                                                             
                                                                   



                                                       
                                                                        




                                                       
                                                           



                                                      






                                                                       

                                               
                                                       
                                                           



                                                      







                                                                             


                               
                           


          
                                
                                
                                                              
 
                                
                                
                                                              
 
                                

                                                 
                                                              
 
                            
                                                     
 





                                                                         
                              
       
                            
       
                                                      
                   

                                


                                                                            
                                                  
                                                     
                





                                                                         
                              
       
                            
       
                                                      
                   
                                
                                           
                   


                                                                            
                                                  
                                                     
                



                                                                         
                                




                                                      
                                                                 






















                                                                  


                                                                               
                                                  

                                                              
                                         




                                                               

                                                                                  
                                                 







                                                                           


                                                   
                                                                    




                                            
                           

          
                                
                                                        
    
                         
                                     
 





                                                                         
                             
       
                           
       
                                                     
                   

                               


                                                                        
                                                  
                                                     
                





                                                                         
                             
       
                           
       
                                                     
                   
                               
                                           
                   


                                                                        
                                                  
                                                     
                



                                                                         

                                                                
                             
       
                           
       
                                                     
                   

                               


                                                                        
                                                  

                                                     





                                                                         
                             
       
                           
       
                                                     
                   
                               
                                           
                   


                                                                        
                                                  

                                                     
 
 



                                                                         
                                                                         





                                                                         
                                                                           

                                                               
                                    
       
                                  
       
                                                            
                   
                                      
                   


                                                    
                                                        




                                                                         
                                                                           

                                                               
                                    
       
                                  
       
                                                            
                   
                                      
                                           
                   


                                                    
                                                        




                                                                         
                                                                           






                                                                        
                   
                                      
                                                         
                   









                                                                           

                                                              
                                    
       
                                  
       
                                                            
                   
                                      
                   


                                                   
                                                        








                                                                         
                                    
       
                                  
       
                                                            
                   
                                      
                                           
                   


                                                   
                                                        



                                                                         








                                                                           
                   
                                      
                                                         
                   








                                                                         
 
                                   




                                               
                                                       
                                                         
                        




                                                                   

                             










                                                                   
                                           
                                                                     
                                                                   

                             
 
                                   
                                                                        

                                                      
                                                                       



                                                                    

                              
 
                               
                           
          
 









                                                                  
                                                    


                                         
                                                  
                                                                           
                                                     

                                                         
                                                                 
                                                                                
                                           








                                                                      
                                                        


                                               
                                                   





                                                              
                        


                              

                                                                           



                                                                            
                                               
                                                                 
                                                                                

                                                                                


                                                 
                                                                                 


                                                                        
 
                               
                           
          
 
                                        
                                                     
 
                                

                                                              
 
                         
                                            

 
 

                                                                         
                                                               
                  







                                                                      
 
                                  
       
                                
       
                                                          
                   
                                    
                   

                                                                  

                                                   
                                                             







                                                                         
                                  
       
                                
       
                                                          
                   
                                    
                                           
                   

                                                                  

                                                   
                                                             



                                                                         

                                                                    
                                         


















                                                                         
 
                                        
                                                              
                                                              
                                                                      




                                               
                                                       
                                                         









                                                                   
                                                                 
                                                   


                                             
                                                       
                                                                     






                                                               












                                                                                

                                                          
                                                                            









                                                               





                                                                   
                                                                   



                             
                                             
                                                      







                                                                              
                        
                                  


                                                       

                                                                                   




                                                               

                                              
                                                               

                             

                                                                
                                                                           



                                                                
                                                                           



                                                                
                                                                           



                                                       
                                                                      
                             
                        
                                             









                                                                   
                                                              
                             

                        
                             

                                                      
                                                                       



                                                                    

                              





                                                               


                                                                               



                                                               







                                                                       


                               
                           

          

                                                         




                                               
                                                                   

                                                            
                        
                                    



                                                                   




                                                                     

                                              
                                                             



                             

                                                     





                                                                               
                        
                                               
                                              
                                                                 

                             
                                              
                                                                
                                                                         
                                             
                                             
                                                                           
                                                               
                                                 

                                                                            


                                                                     
                                                                          
                                                                    


                                        
                                                  
                                              
                                                                    

                             

                             
                                     
                                                      
                                                                       



                                                                    




                               
                           







                                                                    
                                                       





                                                                   

                        
                             

                                                      
                                                                 
                                                        


                                             
                                                       
                                                                     






                                                              
                                                                    

                                                         






                                                         
                                           
                                                       
                                                             



                             
                                              

                                                      










                                                                               






                                                                               
                        
                                       

                                                                 
                        
                                              
                                                       
                                                                


                             
                             

                                                      
                                                                       




                                                                    

                                  




                                                                 




                                                                               
                                                           
                                                   




                                                         
                           









                                                                











                                                                











                                                                
                                                    



                                                     
                                                                        

                                                                           


                                                    

                        

                                           
                                                                            
                                                              

                             

                                                      
                                                                

                                           
                                                                            
                                                              



                                                      
                                                                

                                           
                                                                            
                                                              



                                                      
                                                                




                                                    
                                                    



                                                    
                                                              


                           
                                                         



                                                     
                                                                             

                             
                              
                                                        

                                                                         

                             
                                                   
                                                      
                                                                       
                        
                                                  
                                                    
                                                                      
                        
                                                      
                                                      
                                                                         
                        
                                                      
                                                      
                                                                         
                        
                                                      
                                                      
                                                                         
                        
                              
                                                                          
                                                      
                                                              

                             

                                                      
                                                                      

                                                         
                                                      
                                                                            
                        
                                                         
                                                      
                                                                            
                        
                                                         
                                                      
                                                                            


                        

                                                    
                                                        



                                                   





                                                                    
                        

                                                      
                                                        



                                                     





                                                                      


                                                      
                                                        



                                                     





                                                                      


                                                      
                                                        

                             

                                                     





                                                                      


                                                      
                                                        



                                                     





                                                                      



                               
                           

          
                                  
                             
                                                                 
 
                                   
                                                            
                                                                     

                                   
                                                                     

                                   
                                                                     
 
                                
                                
                                                              
 
                                




                                                    
                                                              
 
                         


                                                          




                                                                         








                                                                   
                   

                                        

                                                                                  















                                                                         
                   
                                        
                                           
                   
                                                                                  
























                                                                                  








                                                                         
                                             

                                 
                                                       
                                                         





                                                                   

                             

                                                      
                                                                 
                                                        

                                 

                                                                         



                                                               
                                                           







                                                                                


                                                            
                                                                   



                             
                                                         
                                                      





                                                                            
                        
                                           









                                                                            
                                                         
                                              
                                                             



                                                       
                                                                          

                                  




                                                                 




                                                                               

                                                           






                                                                  
                                            
                                              
                                                              





                                                      
                                                                          



                                                                    



                               
                           






                                 
                                                               
                                                                       







                                                                   
                                                             



                             
                                           
                                                       
                                                                         
                           


                                                                








                                                                  
                                                  
                                              
                                                                    





                                                      
                                                                       



                                                                    



                               
                           





























                                                                
                                                    



                                                         
                                                                                 
                                                     




                                                                       
                                                          



                                                             
                                                                        




                                                                       
                                                          



                                                             
                                                                        




                                                                       
                                                          



                                                             
                                                                        









                                                                             
                                                                   
                                                         
                                                             

                             
                              
                                                                   
                                                         
                                                             

                             
                              
                                                                   
                                                         
                                                             

                             
                              
                                                                             
                                                         
                                                                       

                             
                                                                       
                                                         
                                                                   


                                                                
                                                              

                             
                                                          
                                                         
                                                                    


                                                               
                                                                          


                                                               
                                                                          


                                                               
                                                                          
                        



                                                             
                                                        



                                                            





                                                                         


                                                             
                                                        



                                                            





                                                                         


                                                             
                                                        



                                                            





                                                                         


                                                         
                                                        



                                                        





                                                                         



                               
                           




                                          
                                                                            


                                                           
                                                                           

                                              
                                                                           

                                              
                                                                           


                                                         


                                                          
                                                              

                         


                                                               




                                                                         


                                                                    
                                     
       
                                   
       
                                                             
                   
                                       
                   

                                                                     

                                                   
                                                             







                                                                         
                                     
       
                                   
       
                                                             
                   
                                    
                                           
                   

                                                                     

                                                   
                                                             




                                                                         
                                                                    





















                                                                         










                                                                             


                                                   














                                                                         
                                           
                   

                                                                             


                                                   



                                                             
 

                                                                         






















                                                                             


                                                                      

                  
                                      
       
                                    
       
                                                              
                   
                                        
                   
                                                  

                                                              




                                                                         


                                                                      

                  
                                      
       
                                    
       
                                                              
                   
                                        
                                           
                   
                                                   

                                                              



                                                                         





















                                                                         
 

                                         
         
                                             
                                               
                                
                                                       
                                                         





                                                                   

                             

                                                      
                                                                 
                                                   
                        

                                             
                                                       
                                                                     
                                            
                                                              




                                                    



                                                               




                                                    

                                              

                                           

                                                                     

                             
 





                                                                              



                                                    
                                      

                                                                        

                                                  
                                            


                                                                     



                                                    
                                                     
                                              
                                                                       

                             
                                            
                                                       
                                                                          
                        
                                  





                                                               






                                                                                  

                                                                   
                                                     


                                                  


                                                                  

                                                    

                              
                                            
                                              
                                                              

                             


                                                             
                                                      
                                                                       



                                                                    

                              











                                                                       
                        


                                                                   

                             

                                              
                                                            


                           


                                                                           
                        









                                                                  
                        
                                                    
                                              
                                                                     



                                                   

                                                                       




                                                                    
                        

                               
                           




                             

                                                      


                                                                

                                                      


                                                                

                                                      


                                                                

                                                      



                                                                


                                                      
                                                    

                             



                                                                              

                        



                                                                    

                             


                                                                     
                        




                                                                    

                             


                                                                     
                        




                                                                    

                             


                                                                     

                        
 
                           








                                                                             

                             



                                                                       

                             



                                                                       

                             
                              


                                                                         

                             


                                                                               
                        

                                                                  
                                                              

                             


                                                                      
                        


                                                                              
                        


                                                                              
                        


                                                                              

                        
 
                        

                                                               
                                                        

                             

                                                              

                                                              
                                                                      


                                                    
                        

                                                               
                                                        

                             

                                                              

                                                              
                                                                      


                                                    
                        

                                                               
                                                        

                             

                                                              

                                                              
                                                                      


                                                    
                        

                                                           
                                                        

                             

                                                          

                                                              
                                                                      


                                                    
                        
 
 
                               
                           

          
 












                                                                             

                                  



                                                    
                                                              

                         
                                                                         

 
 








                                                                          
 
                                  
       
                                
       
                                                          
                   
                                    
                   
                                                                  
                                                  







                                                                         
                                                                  

                  
                                  
       
                                
       
                                                          
                   
                                    
                                           
                   
                                                                  
                                                   






                                                                         





















                                                                         
 




                                                             

                                             
                                 
                                
                                                       
                                                         
                        








                                                                   
                                                                 


                                                        

                                                                         






                                                               










                                                                                











                                                               








                                                                              






















                                                                                    
                                                  

















                                                                                    
                                                  



















                                                                                    
                                                  



































































                                                                        
 















































                                                                       





                                                               






                                                                                  

                                                                    
                                                     


                                                    


































                                                                                  

                                                 


















                                                                   



                                                                          







































































































































































































































































































































































































                                                                                

                               
                                               


                            

                                  
                                                             
                                          
                                                      
                                                   




                                                     
                                       

                                                      
                             

                 


                                
                                            





                                               
                                         
                                          
                                              
                     





                                                                     






                                        
                                          

                                  







                                                         




                                                  
                                      


                                                  
                                               










                                                
                                     


                                         
                              

                          

                                                     
                              
                                    




















                                                                    
                                                                     





                                                            

                                               





















                                                
                                             



                                           


                                                     

                                    
 















                                                                         
                   

                                       

                                                                     















                                                                         
                   
                                       
                                           
                   

                                                                     

                                                   





















                                                                         




                                                                         



                                                                   
                  



                                                                          
                                                         
  
 
                                               
       
                                             
       
                                                                       
                   
                                                 
                   







                                                              
                                               



                                                                  


                
                                                                         



                                                                   

                  
                                               
       
                                             
       

                                                                       
                                           
                   








                                                              
































                                                                         



                                                                  


                





                                                                         
















                                                                   
                                                                   
                                                                 


                                                        

                                                                      






                                                               









                                                                                

                                                          
                                                                            









                                                               




                                                                              







                                                                       
                                                                         

                            
                                                                  

                                                       





                                                                              



                                                    





                                                                   





                                                               
                                                 
                                                       
                                                                    
                        



                                                             
                        






                                                                           



                                                    



                                                             
                        


                                                                    
                        



                                                             
                        





                                                                            




                                                    




                                                             
 
                       








                                                                       










                                                                 

                                         


                                                                 
                                              
                                   




                                                                               

                                                            





                                                                   

























                                                                   
                                                                        

                                                              

                                                 






                                                                  



                                                                    








                                                                   



                                                                          





























                                                                        
                                                                     







                                                                
                                           

                                                       
                                                                         

                                                                           
                                                                      



                                                    


                                                  


                                                                      
                                                        

                                                        

                                                                  
                        
                                           
                                              
                                                             


                             

                                               
                                           



























































































































































                                                                                

                             




                                                                 

                             



                                                                 

                             




                                                                     

                             



                                                             

                             




                                                                 


                             


                                                             

                             





                                                                 
                        





                                                              

                             





                                                                  
                        



                                                    


                                                        

                                                   

                                                              
                                                                       

























                                                                       
                                                              
                                                              
                                                               

                                                              


                                                              
                                                              

                                                              

                                  


                                                             


                                                              
                                                     
 
 
                                     
                  
                                                     


                            

                                  
                                                             
                                          
                                                      
                                                   










                                                         
                                       

                                                      
                             

                 


                                
                                            

       

                                               

                             
                                         
                                          
                                              





                                       

                                        
                                          

                                  







                                                         



                                
                                                  

                                        









                                                       
 


                                           






                                          

















                                            
                                     
                                         

                              
                              

                          

                                                     
                              
                                    

        

                                                   









                                                                    
                                      
                      
                                                                


                                         








                                                             

                 

                                 




                                            
                                             

                                         
                                          


                                                

                                                 

                        


                                                 





                                              
                                             



                                           


                                                     

                                    

                                                           





                                                                         
                                                                   
                                                                     

                                                                  

                  
                                                  
       
                                                
       

                                                                          

                                  













                                                                      




                                                    
                                                                  



                                                                         
                                                                   
                                                                     

                                                                  

                  
                                                  
       
                                                
       

                                                                          
                                           
                   
                                  










                                                                      

                                                                   
                                   




                                                    
                                                                  



                                                                         



















                                                                          






                                                                              




















                                                                              
























                                                                               






















                                                                               








                                                                     
                                                         









                                                                               



































                                                                                 

































                                                                                 








                                                                           
                                                         




















                                                                                 


























                                                                      

                                                                























































































































































































































































































































































                                                                                 

                                                                















































































































































































































































































































































































































































































                                                                                  
 























                                                                            






























                                                                               


























                                                                               








                                                                           
                                                         













                                                                               




























                                                                                  


































                                                                                  
















                                                                           
                                                         





















                                                                                  



















































































































































































































































































































































































































































                                                                                 
                                                                                






                                                                              










                                                                                





























































































                                                                                  
                                                                    









                                                                                 












                                                                                 




















































































































































































































































                                                                               
                                                                         










                                                                          
                   

                                             

                                                
















                                                                          
                   
                                             
                                           
                   























                                                                          



                                                                   

                                                                         

















                                                                   
                                                                 


                                                        

                                                                      






                                                               










                                                                                











                                                               







                                                                  
































                                                                               
                                                                             






                                                                        
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                             






                                                                               
                                        


                                                         
                                                                              






                                                                               
                                          
















                                                                                    
                                                                    

                                                          

                                                                    





















                                                                       




                                                                 




                                                                               

                                                            
                                                      
                                                          











                                                                   
                                                           












                                                                   
                                                                                 

                                                              

                                                 


















                                                                    



                                                                          




                                                        
                                                                  











                                                               
                                                                       










                                                                    
                                                                     










                                                                

                                                                   














                                                                           
                                                                       









                                                                       


                             


                                                       

                                                                    





                                                                           
                        
















                                                                             



                                                    
















                                                                             



                                                    








                                                                             
                        









                                                                        
                        
















                                                                             


                                                    
                        
















                                                                             



                                                    








                                                                             
                        









                                                                        
                        
















                                                                             



                                                    








                                                                             
                        






                                                                        

                                                    
                              
                        








                                                                             
                        









                                                                        
                        








                                                                             
                        






                                                                        



                                                    
















                                                                        
                                              

                                                                        



                                                   



                                                                            



                                                                    

                              


                                                           

                             




                                                                
                        


                                                   
                        





                                                                 

                        


                               
 





                                                                

                             



                                                                

                        



                                                    

                             



                                                                                

                        




                                                              

                             


                                                                   
                        



                                                    
                                                               

                             
                              


                                                                

                             




                                                                   

                             




                                                                     
                        






                                                       
                        
 



                                                                        

                             





















                                                                                 


                                                    
                        



                                                                                   

                             





















                                                                                  


                                                    
                        



                                                    
                                                        

                             

                                                   

                                                              

                                                                       


                                                    
                        

                                                    
                                                        

                             

                                                   

                                                              

                                                                       


                                                    



                               
                           

          


                                                              
 


                                                              

                                  

                                                 
                                                              

                         





                                                     
                                                     

                            
                                 
                                                                 





                                                            
                                             




















                                                                   


                                      
                                            
                                                                   
                                          
                                                            

                                                         




                                                     
                                               
                                                
                                              







                                              
                                          

                                  







                                                         



















                                                        
                                           


                                               
                              

                          

                                                     
                              
                                    
        
 







                                                         

 

                                                                         












                                                                            
                   

                          

                                                      
                                                
                                               


                                                                      
                

 
 
                                                                         












                                                                            
                   

                          
                                                      
                                           
                   
                                                 




























                                                                            


                                                                      
                
 

                                                                         

                                                                      



                                                                       
                                                    
 
                                                     
       
                                                   
       



                                                                             
                   
                                  
                                                
                                               

                                                
                                                                      



                                                                         
                                                                      




                                                                       
                                                    
 
                                                     
       
                                                   
       



                                                                             
                                           
                   

                                                 
                                               

                                                
                                                                      


                
 
                                                                         





                                                                       




























                                                                             
                                                   
 
                                                    
       
                                                  
       
                                                                            
                   


                                                      
                   
                                                
                                               


                                                                      
                


                                                                         





                                                                       
                                                   
 
                                                    
       
                                                  
       



                                                                            
                                           
                   
                                  
                                                 
                                               


                                                                      
                
 

 
                                                                         
















                                                                            



                                                      







                                                                      








                                                               


                                                                         


















                                                                                  
                                               






















                                                                                  
                                           
                   
                                  
                                                 
                                               













                                                                            






                                                                                  




                                                            
                                  















                                                                            












                                                                                   
                                               






















                                                                                   
                                           

                                  
                                                 
                                               







                                                                            




























                                                                                   





                                                                       
                                                   
 
                                                          
       
                                                        
       



                                                                                  
                   
                                  
                                                
                                               


                                                                            









                                                                            
                                                   
 
                                                          
       
                                                        
       



                                                                                  
                                           
                   
                                  
                                                 
                                               


                                                                            



                                                                         



























                                                                                  

                                                                   



                                                                       
                                                    
 
                                                           
       
                                                         
       



                                                                                   
                   
                                  
                                                
                                               

                                                
                                                                            
                
 
 
                                                                         
                                                                            




                                                                       
                                                    
 
                                                           
       
                                                         
       



                                                                                   
                                           
                   
                                  

                                                 

                                                
                                                                            
                
 
 
                                                                         

















                                                                                   
                                  








                                                                            












                                                                                  

                          
                                                            
                                                                           
                   
                                  
                                                
                                               


                                                                            


                









                                                                              













                                                                                  

                          
                                                            



                                                                     
                   
                                  
                                                 
                                               


                                                                            




                                                                         

















                                                                                  
                                  









                                                                            






                                                                       
 








                                                                                  
                                  
                                                
                                               



                                                                            
 
 
















                                                                                  
                                           
                   
                                  
                                                 
                                               






                                                                            

















                                                                                  
                                  








                                                                            
















                                                                                   
                                  
                                                
                                               






















                                                                                   
                                           
                   
                                  

                                                 







                                                                            

















                                                                                   
                                  









                                                                            










                                                            


                                                                            






                                                          





                                                          
               


                                                              








                                                      











                                                                      




                                                                    
                                                                    

                                                                 
                                           

                                                                               


                                                 


                                                                          


                                                          



                                                                    

                                                                 
                                           

                                                                               


                                                 


                                                                          


                                                          


                            
                                                                   



                                                                         












                                                                   
 


                                                      
                                                                 


                                                        

                                                                      






                                                               









                                                                                

                                                          
                                                                            




                                                               
                                        
                                                                          

                                         




                                               




                                                                              




































                                                                                 

                                                       
                                                                            





































































                                                                          




                                                                 




                                                                               

                                                            
                                                      
                                                          




























                                                                                  

                                                 



















                                                                           
                                            




                                                        

                                                                         





















































































































































































































                                                                                
                                                                    













                                                                               





                                                                                
                                                             

                                                                               


                                                                       

                                                                               

                                                                        



                                                    


                                                            

                                                    


                                                                      
                                                                       









































                                                                       
                                                                  
























                                                                   
                                                             

                                                 
                                                            

                                                         
                               







































                                                          
                                                 


                                                                                


                                            

                                                                     


                                                                

                                                                       

                                                                      




                                                                












                                                                                 
                                             

                            

                                
                                                                                
                                          

                                                                




                                                                 
                                                                         

                                                        
                                          
                               

                 
                              


                                            
















                                                            
                                                       

                     
                                                                 










                                                     

                                                        
                          
                                                              


                  
                                                              













                                                                
                                                         
                                                                  
                                                                                    

                                              

                                                                  

                                                
                                                                      


                                                                       

                                                            

                                                                    


                                            

                                                            


                                    

                                                   
                     
                               





                                         
                                          

                                  









                                                         









                                              
                                        

                              
                              

                          

                                                     
                              
                                    

        

    



















                                                                      
                              












                                                                              
                              












                                                                


                                                               

                           



                                                                                   


                             





                                             
 



                                        
 







                                         
 

                                                                         
                    
 










                                                            
 







                                                                            
                             











                                                            

 


                                                                    

                                                                




                                                                                   

                                                                





                                                                                   

                                                             





                                                                                
 













                                                                   
 


                                                      
                                                                 

                                                        
                                   

                                                                      






                                                              








                                                                    









































                                                                            




                                                                             



                                                                       
 







                                                                     
                                            
                                                       
                                                                    








                                                                      
 











                                                                    


                                                                 






                                                                                 


                             








































































                                                                                  

                                                 




















                                                                     
                                            



                                                        

                                                                         
















































































































































































































































                                                                                
 

                                                                  
                                                                  












































                                                                   

                                                                 









                                                                     
                                       



                                                                     
                                                          








                                                                              


                                                 
                
                          

                                                           




                                                       


                                                






                                           
                                                                             

                            


                                        
                                                                                 

                                                 
                                          

                                                         
                                      

                                                                  

                                        

                                                                           
                         
                                                         
                                   
                                                     
                                               
                                   


                               
                                      


                                            

       

                                                                
                             

                                                                 






                                                                          


                                                                   
                                                                          

                                                    

                                                

                                                                        










                                                                               





















                                                                               









                                           

                                                  

                                                                             
                                                           




                                                      

                                                          
                                          
                                                                          
                                                           
                                                   
                                                  
                                                           

                                            
                                                           
                 


                                       

        











                                                                     















































                                                                 

                                             







                                       
                                          






                                  
                                 

                              
                              

                          

                                                 
                              
                                    


        



                                                                         




                                                    




                                      

                                                            
                                           
                      







                                                                         





                                                                    





                                      

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                            
                                           
                      



















                                                                         

                                                            
                                           
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      
                    
                          

















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      
                    
                          

















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      
                    
                          

















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      
                    
                          

















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      









                                                                         























                                                                         









                                                        

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      







                                                                         























                                                                         











                                                                    

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      









                                                                         
                                                       








                                                   

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      









                                                                         























                                                                         









                                                       

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      







                                                                         

                                                                    























                                                                         









                                                       

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      



















                                                                         

                                                             
                                            
                      



















                                                                         

                                                             
                                            
                      







                                                                         











                                                                    

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      











                                                                         























                                                                         







                                         

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      










                                                                         























                                                                         








                                                       

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      









                                                                         























                                                                         









                                                       

                                                               
                                              
                      



















                                                                         

                                                               
                                              
                      











                                                                         























                                                                         







                                        

                                                              
                                             
                      



















                                                                         

                                                              
                                             
                      







                                                                         























                                                                         
 





















                                                                   
                                                                















                                                          










                                         
             
                  



                                   

                   
                     
                                                                               
                                                                



                                  

                                                                     














                                                                         





















                                                                   

                                                 







                                                                  













                                                                              

                                                    


                                                                              







                                                                 





                                                                   





















































                                                                             







                                                                   
















                                                                   

                                                 




















                                                                      

























                                                                               












                                                                               


                                                                    










                                                                             





































































                                                                          






                                                                            






                                                            





                                                          






















































                                                                       






                                                            




                                                    




                                                                          


























































                                                                                            



                                         
                                


                                         




                                                                       


                                                  







                                                                                 







                                                                             






                                                              


                                                       
                                                                        
                                                     
                                                


                                                      






                                                                        
                                   
                                                                             

                                                           


                                                         
                                                          
                                                      


                                                                               

                                                                             
                                                


                                                      


                                                         
                                                          
                                                      


                                                                               

                                                                         
















































































































































































                                                                                    





                                                                   
                             














                                                                            


                                                                             







                                                           
















                                                         




                             
    














                                                                         





















                                         













                                                             




                                                                         




                                             





                                 



                                                                       






                                                                                  




                                                                           

                
 
                                                                          





                                                                     


                                         

            

                                          
                                  
 
                                                    

                                                              
                                  
                                              
                                

                               
                          
                         

        
 
 
                                    





                                                              
                                  

 


                                                                         






                                                                  
                             


                                                     
                                                    
                                          








                                                          

                                                             
               
                                                          
        
 


                                               


                                                 













                                                     


                                          


                                           


                                              


                                              
 

                                                 
 

                                                  
 
 

                                       
 

                                           
 
                                           



                                                   
                                                                    
        
 
 
 
 







                                                                      
                                   

                     
                                  
            



                                          
                                         
               


        
                                                                  
                                                                     

                          
                            




                                                                         























                                                                         
 


                                









                                                                         
           
 

                                         































                                                                         

                                           




                                                                             

                                    



                                                                             















                                                                   
                   








                                     
                                                                              




                                                                
                         







                                                              

                           
                                   

                          
                                 
                                          
         
                                                                      




                                                          
                 







                                                        


        

                                   
 


















                                                   
   

                                                                         


                         


                         


                           




                                       
 

                       
 















                                                                        

 

                            
 











                                                                          
 

             
 
          



                                                     
%%
%% %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").
-include("socket_test_evaluator.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_connect_tcp6/1,
         api_a_sendto_and_recvfrom_udp4/1,
         api_a_sendto_and_recvfrom_udp6/1,
         api_a_sendmsg_and_recvmsg_udp4/1,
         api_a_sendmsg_and_recvmsg_udp6/1,
         api_a_send_and_recv_tcp4/1,
         api_a_send_and_recv_tcp6/1,
         api_a_sendmsg_and_recvmsg_tcp4/1,
         api_a_sendmsg_and_recvmsg_tcp6/1,
         api_a_recvfrom_cancel_udp4/1,
         api_a_recvfrom_cancel_udp6/1,
         api_a_recvmsg_cancel_udp4/1,
         api_a_recvmsg_cancel_udp6/1,
         api_a_accept_cancel_tcp4/1,
         api_a_accept_cancel_tcp6/1,
         api_a_recv_cancel_tcp4/1,
         api_a_recv_cancel_tcp6/1,
         api_a_recvmsg_cancel_tcp4/1,
         api_a_recvmsg_cancel_tcp6/1,
         api_a_mrecvfrom_cancel_udp4/1,
         api_a_mrecvfrom_cancel_udp6/1,
         api_a_mrecvmsg_cancel_udp4/1,
         api_a_mrecvmsg_cancel_udp6/1,
         api_a_maccept_cancel_tcp4/1,
         api_a_maccept_cancel_tcp6/1,
         api_a_mrecv_cancel_tcp4/1,
         api_a_mrecv_cancel_tcp6/1,
         api_a_mrecvmsg_cancel_tcp4/1,
         api_a_mrecvmsg_cancel_tcp6/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_sock_acceptconn_udp/1,
         api_opt_sock_acceptconn_tcp/1,
         api_opt_sock_acceptfilter/1,
         api_opt_sock_bindtodevice/1,
         api_opt_sock_broadcast/1,
         api_opt_sock_debug/1,
         api_opt_sock_domain/1,
         api_opt_sock_dontroute/1,
         api_opt_sock_error/1,
         api_opt_sock_keepalive/1,
         api_opt_sock_linger/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_counters_tcp4/1,
         traffic_send_and_recv_counters_tcp6/1,
         traffic_send_and_recv_counters_tcpL/1,
         traffic_sendmsg_and_recvmsg_counters_tcp4/1,
         traffic_sendmsg_and_recvmsg_counters_tcp6/1,
         traffic_sendmsg_and_recvmsg_counters_tcpL/1,
         traffic_sendto_and_recvfrom_counters_udp4/1,
         traffic_sendto_and_recvfrom_counters_udp6/1,
         traffic_sendto_and_recvfrom_counters_udpL/1,
         traffic_sendmsg_and_recvmsg_counters_udp4/1,
         traffic_sendmsg_and_recvmsg_counters_udp6/1,
         traffic_sendmsg_and_recvmsg_counters_udpL/1,

         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
        ]).


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


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

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

-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(F(F, A),    ?LIB:f(F, A)).


-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_close, "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_socket,          [], api_options_socket_cases()},
     {api_option_sock_acceptconn,  [], api_option_sock_acceptconn_cases()},
     {api_options_ip,              [], api_options_ip_cases()},
     %% {api_options_ipv6,           [], api_options_ipv6_cases()},
     %% {api_options_tcp,            [], api_options_tcp_cases()},
     %% {api_options_udp,            [], api_options_udp_cases()},
     %% {api_options_sctp,           [], api_options_sctp_cases()},
     {api_op_with_timeout,         [], api_op_with_timeout_cases()},
     {socket_close,                [], socket_close_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_counters,            [], traffic_counters_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_connect_tcp6,
     api_a_sendto_and_recvfrom_udp4,
     api_a_sendto_and_recvfrom_udp6,
     api_a_sendmsg_and_recvmsg_udp4,
     api_a_sendmsg_and_recvmsg_udp6,
     api_a_send_and_recv_tcp4,
     api_a_send_and_recv_tcp6,
     api_a_sendmsg_and_recvmsg_tcp4,
     api_a_sendmsg_and_recvmsg_tcp6,
     api_a_recvfrom_cancel_udp4,
     api_a_recvfrom_cancel_udp6,
     api_a_recvmsg_cancel_udp4,
     api_a_recvmsg_cancel_udp6,
     api_a_accept_cancel_tcp4,
     api_a_accept_cancel_tcp6,
     api_a_recv_cancel_tcp4,
     api_a_recv_cancel_tcp6,
     api_a_recvmsg_cancel_tcp4,
     api_a_recvmsg_cancel_tcp6,
     api_a_mrecvfrom_cancel_udp4,
     api_a_mrecvfrom_cancel_udp6,
     api_a_mrecvmsg_cancel_udp4,
     api_a_mrecvmsg_cancel_udp6,
     api_a_maccept_cancel_tcp4,
     api_a_maccept_cancel_tcp6,
     api_a_mrecv_cancel_tcp4,
     api_a_mrecv_cancel_tcp6,
     api_a_mrecvmsg_cancel_tcp4,
     api_a_mrecvmsg_cancel_tcp6
    ].

api_options_cases() ->
    [
     {group, api_options_otp},
     {group, api_options_socket},
     {group, api_options_ip}% ,
     %% {group, api_options_ipv6},
     %% {group, api_options_tcp},
     %% {group, api_options_udp},
     %% {group, api_options_sctp}
    ].

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

api_options_socket_cases() ->
    [
     {group, api_option_sock_acceptconn},
     api_opt_sock_acceptfilter,
     api_opt_sock_bindtodevice,
     api_opt_sock_broadcast,
     api_opt_sock_debug,
     api_opt_sock_domain,
     api_opt_sock_dontroute,
     api_opt_sock_error,
     api_opt_sock_keepalive,
     api_opt_sock_linger
    ].

api_option_sock_acceptconn_cases() ->
    [
     api_opt_sock_acceptconn_udp,
     api_opt_sock_acceptconn_tcp
    ].

api_options_ip_cases() ->
    [
     api_opt_ip_add_drop_membership
    ].

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

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_close_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_counters},
     {group, traffic_chunks},
     {group, traffic_pp_send_recv},
     {group, traffic_pp_sendto_recvfrom},
     {group, traffic_pp_sendmsg_recvmsg}
    ].

traffic_counters_cases() ->
    [
     traffic_send_and_recv_counters_tcp4,
     traffic_send_and_recv_counters_tcp6,
     traffic_send_and_recv_counters_tcpL,
     traffic_sendmsg_and_recvmsg_counters_tcp4,
     traffic_sendmsg_and_recvmsg_counters_tcp6,
     traffic_sendmsg_and_recvmsg_counters_tcpL,
     traffic_sendto_and_recvfrom_counters_udp4,
     traffic_sendto_and_recvfrom_counters_udp6,
     traffic_sendto_and_recvfrom_counters_udpL,
     traffic_sendmsg_and_recvmsg_counters_udp4,
     traffic_sendmsg_and_recvmsg_counters_udp6,
     traffic_sendmsg_and_recvmsg_counters_udpL
    ].

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(string:trim(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("Welcome to SUSE Linux " ++ _) ->
    has_bugfree_gcc4(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.

has_bugfree_gcc4("gcc (SUSE Linux) 4.3.2" ++ _) ->
    skip("Buggy GCC");
has_bugfree_gcc4(_) ->
    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. IPv4.

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() ->
                   ok = api_a_connect_tcpD(inet)
           end).


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

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

api_a_connect_tcp6(suite) ->
    [];
api_a_connect_tcp6(doc) ->
    [];
api_a_connect_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_connect_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   ok = api_a_connect_tcpD(inet6)
           end).


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

api_a_connect_tcpD(Domain) ->
    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  => Domain,
                  connect => Connect,
                  send    => Send,
                  recv    => Recv},
    api_a_connect_tcp(InitState).


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

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 IPv6 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_udp6(suite) ->
    [];
api_a_sendto_and_recvfrom_udp6(doc) ->
    [];
api_a_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_a_sendto_and_recvfrom_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Send = fun(Sock, Data, Dest) ->
                                  socket:sendto(Sock, Data, Dest)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recvfrom(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet6,
                                 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).



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

%% Basically send and receive on an IPv6 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_udp6(suite) ->
    [];
api_a_sendmsg_and_recvmsg_udp6(doc) ->
    [];
api_a_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(5)),
    tc_try(api_a_sendmsg_and_recvmsg_udp6,
           fun() -> has_support_ipv6() end,
           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 => inet6,
                                 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 "common" functions (send and recv)
%% on an IPv6 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_tcp6(suite) ->
    [];
api_a_send_and_recv_tcp6(doc) ->
    [];
api_a_send_and_recv_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_send_and_recv_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Send = fun(Sock, Data) ->
                                  socket:send(Sock, Data)
                          end,
                   Recv = fun(Sock) ->
                                  socket:recv(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet6,
                                 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).



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

%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an IPv6 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_tcp6(suite) ->
    [];
api_a_sendmsg_and_recvmsg_tcp6(doc) ->
    [];
api_a_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_sendmsg_and_recvmsg_tcp6,
           fun() -> has_support_ipv6() end,
           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 => inet6,
                                 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. IPv4
%%
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 recvfrom,
%% wait some time and then cancel. IPv6
%%
api_a_recvfrom_cancel_udp6(suite) ->
    [];
api_a_recvfrom_cancel_udp6(doc) ->
    [];
api_a_recvfrom_cancel_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recvfrom_cancel_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvfrom(Sock, 0, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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).



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

%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel. IPv6
%%
api_a_recvmsg_cancel_udp6(suite) ->
    [];
api_a_recvmsg_cancel_udp6(doc) ->
    [];
api_a_recvmsg_cancel_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recvmsg_cancel_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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).




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

%% Basically we make an async (Timeout = nowait) call to accept,
%% wait some time and then cancel. IPv6
%%
api_a_accept_cancel_tcp6(suite) ->
    [];
api_a_accept_cancel_tcp6(doc) ->
    [];
api_a_accept_cancel_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_accept_cancel_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Accept = fun(Sock) ->
                                    case socket:accept(Sock, nowait) of
                                        {ok, _} = OK ->
                                            OK;
                                        {select, _} = SELECT ->
                                            SELECT;
                                        {error, _} = ERROR ->
                                            ERROR
                                    end
                            end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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 recv,
%% wait some time and then cancel. IPv6
%%
api_a_recv_cancel_tcp6(suite) ->
    [];
api_a_recv_cancel_tcp6(doc) ->
    [];
api_a_recv_cancel_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recv_cancel_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recv(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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).



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

%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel. IPv6
%%
api_a_recvmsg_cancel_tcp6(suite) ->
    [];
api_a_recvmsg_cancel_tcp6(doc) ->
    [];
api_a_recvmsg_cancel_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_a_recvmsg_cancel_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recvmsg(Sock, nowait)
                          end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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 recvfrom
%% (from *several* processes), wait some time and then cancel.
%% This should result in abort messages to the 'other' processes. IPv6
%%
api_a_mrecvfrom_cancel_udp6(suite) ->
    [];
api_a_mrecvfrom_cancel_udp6(doc) ->
    [];
api_a_mrecvfrom_cancel_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecvfrom_cancel_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvfrom(Sock, 0, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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).



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

%% 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. IPv6
%%
api_a_mrecvmsg_cancel_udp6(suite) ->
    [];
api_a_mrecvmsg_cancel_udp6(doc) ->
    [];
api_a_mrecvmsg_cancel_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecvmsg_cancel_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  case socket:recvmsg(Sock, nowait) of
                                      {ok, _} = OK ->
                                          OK;
                                      {select, _} = SELECT ->
                                          SELECT;
                                      {error, _} = ERROR ->
                                          ERROR
                                  end
                          end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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).




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

%% 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. IPv6
%%
api_a_maccept_cancel_tcp6(suite) ->
    [];
api_a_maccept_cancel_tcp6(doc) ->
    [];
api_a_maccept_cancel_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_maccept_cancel_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Accept = fun(Sock) ->
                                    case socket:accept(Sock, nowait) of
                                        {ok, _} = OK ->
                                            OK;
                                        {select, _} = SELECT ->
                                            SELECT;
                                        {error, _} = ERROR ->
                                            ERROR
                                    end
                            end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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 recv
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes. IPv6
%%
api_a_mrecv_cancel_tcp6(suite) ->
    [];
api_a_mrecv_cancel_tcp6(doc) ->
    [];
api_a_mrecv_cancel_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecv_cancel_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recv(Sock, 0, nowait)
                          end,
                   InitState = #{domain => inet6,
                                 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. IPv4
%%
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).



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

%% 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. IPv6
%%
api_a_mrecvmsg_cancel_tcp6(suite) ->
    [];
api_a_mrecvmsg_cancel_tcp6(doc) ->
    [];
api_a_mrecvmsg_cancel_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(20)),
    tc_try(api_a_mrecvmsg_cancel_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   Recv = fun(Sock) ->
                                  socket:recvmsg(Sock, nowait)
                          end,
                   InitState = #{domain => inet6,
                                 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 the socket option acceptconn for UDP.
%% This should be possible to get but not set.

api_opt_sock_acceptconn_udp(suite) ->
    [];
api_opt_sock_acceptconn_udp(doc) ->
    [];
api_opt_sock_acceptconn_udp(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(api_opt_sock_acceptconn_udp,
           fun() ->
                   has_support_sock_acceptconn()
           end,
           fun() -> api_opt_sock_acceptconn_udp() end).



api_opt_sock_acceptconn_udp() ->
    Opt = acceptconn,
    Set = fun(S, Val) ->
                  socket:setopt(S, socket, Opt, Val)
          end,
    Get = fun(S) ->
                  socket:getopt(S, socket, Opt)
          end,

    TesterSeq =
        [
         #{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 => "[get] verify socket (before bind)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Not accepting connections"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Accepting connections"),
                                   {error, {unexpected_success, {Opt, true}}};
                               {error, enoprotoopt = Reason} ->
                                   %% On some platforms this is not accepted
                                   %% for UDP, so skip this part (UDP).
                                   ?SEV_EPRINT("Expected Failure: "
                                               "~p => SKIP", [Reason]),
                                   (catch socket:close(Sock)),
                                   {skip, Reason};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify socket (before bind)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case Set(Sock, true) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p",
                                               [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=true)"),
                                   {error, unexpected_success}
                           end
                   end},

         #{desc => "bind socket to local address",
           cmd  => fun(#{sock := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "[get] verify socket (after bind)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Not accepting connections"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Accepting connections"),
                                   {error, {unexpected_success, {Opt, true}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify socket (after bind)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           case Set(Sock, true) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p",
                                               [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=true)"),
                                   {error, unexpected_success}
                           end
                   end},

         %% *** Termination ***
         #{desc => "close socket",
           cmd  => fun(#{sock := Sock} = State) ->
                           socket:close(Sock),
                           {ok, maps:remove(sock, State)}
                   end},

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

    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain  => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option acceptconn for TCP.
%% This should be possible to get but not set.

api_opt_sock_acceptconn_tcp(suite) ->
    [];
api_opt_sock_acceptconn_tcp(doc) ->
    [];
api_opt_sock_acceptconn_tcp(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(api_opt_sock_acceptconn_tcp,
           fun() ->
                   has_support_sock_acceptconn()
           end,
           fun() -> api_opt_sock_acceptconn_tcp() end).



api_opt_sock_acceptconn_tcp() ->
    Opt = acceptconn,
    Set = fun(S, Val) ->
                  socket:setopt(S, socket, Opt, Val)
          end,
    Get = fun(S) ->
                  socket:getopt(S, socket, Opt)
          end,

    TesterSeq =
        [
         #{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 => "[get] verify listen socket (before bind)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Not accepting connections"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Accepting connections"),
                                   {error, {unexpected_success, {Opt, true}}};
                               {error, enoprotoopt = Reason} ->
                                   ?SEV_EPRINT("Expected Failure: "
                                               "~p => SKIP", [Reason]),
                                   (catch socket:close(Sock)),
                                   {skip, Reason};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify listen socket (before bind)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Set(Sock, true) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=true)"),
                                   {error, unexpected_success}
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "bind listen socket to local address",
           cmd  => fun(#{lsock := Sock, local_sa := LSA} = State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{server_sa => LSA#{port => Port}}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "[get] verify listen socket (after bind)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Not accepting connections"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Accepting connections"),
                                   {error, {unexpected_success, {Opt, true}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify listen socket (after bind)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Set(Sock, true) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=true)"),
                                   {error, unexpected_success}
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "make listen socket accept connections",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case socket:listen(Sock) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "[get] verify listen socket (after listen)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, true} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Accepting connections"),
                                   ok;
                               {ok, false} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Not accepting connections"),
                                   {error, {unexpected_success, {Opt, false}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify listen socket (after listen)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Set(Sock, false) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=false)"),
                                   {error, unexpected_success}
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "create (connecting) socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{csockc => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "bind connecting socket to local address",
           cmd  => fun(#{csockc := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "[get] verify connecting socket (before connect)",
           cmd  => fun(#{csockc := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Not accepting connections"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Accepting connections"),
                                   {error, {unexpected_success, {Opt, true}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify connecting socket (before connect)",
           cmd  => fun(#{csockc := Sock} = _State) ->
                           case Set(Sock, true) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=true)"),
                                   {error, unexpected_success}
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "connect to server",
           cmd  => fun(#{csockc := Sock, server_sa := SSA} = _State) ->
                           case socket:connect(Sock, SSA) of
                               ok ->
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "accept connection",
           cmd  => fun(#{lsock := Sock} = State) ->
                           case socket:accept(Sock) of
                               {ok, CSock} ->
                                   {ok, State#{csocks => CSock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "[get] verify connecting socket (after connect)",
           cmd  => fun(#{csockc := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Not accepting connections"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Accepting connections"),
                                   {error, {unexpected_success, {Opt, true}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify connecting socket (after connect)",
           cmd  => fun(#{csockc := Sock} = _State) ->
                           case Set(Sock, true) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=true)"),
                                   {error, unexpected_success}
                           end
                   end},

         #{desc => "[get] verify connected socket",
           cmd  => fun(#{csocks := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Not accepting connections"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Accepting connections"),
                                   {error, {unexpected_success, {Opt, true}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify connected socket",
           cmd  => fun(#{csocks := Sock} = _State) ->
                           case Set(Sock, true) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=true)"),
                                   {error, unexpected_success}
                           end
                   end},

         #{desc => "[get] verify listen socket (after connect)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, true} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "Accepting connections"),
                                   ok;
                               {ok, false} ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Not accepting connections"),
                                   {error, {unexpected_success, {Opt, false}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[set] verify listen socket (after connect)",
           cmd  => fun(#{lsock := Sock} = _State) ->
                           case Set(Sock, false) of
                               {error, Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   ok;
                               ok ->
                                   ?SEV_EPRINT("Unexpected Success: "
                                               "Set acceptconn (=false)"),
                                   {error, unexpected_success}
                           end
                   end},

         %% *** Termination ***
         #{desc => "close connecting socket(s)",
           cmd  => fun(#{csockc := Sock} = State0) ->
                           socket:close(Sock),
                           State1 = maps:remove(csockc, State0),
                           State2 = maps:remove(csocks, State1), %% Auto-close
                           {ok, maps:remove(csockc, State2)}
                   end},
         #{desc => "close listen socket",
           cmd  => fun(#{lsock := Sock} = State) ->
                           socket:close(Sock),
                           {ok, maps:remove(lsock, State)}
                   end},

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


    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain  => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option acceptfilter. PLACEHOLDER!

api_opt_sock_acceptfilter(suite) ->
    [];
api_opt_sock_acceptfilter(doc) ->
    [];
api_opt_sock_acceptfilter(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(api_opt_sock_acceptfilter,
           fun() -> not_yet_implemented() end,
           fun() -> ok end).



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

%% Tests the socket option bindtodevice.
%% It has not always been possible to 'get' this option
%% (atleast on linux).

api_opt_sock_bindtodevice(suite) ->
    [];
api_opt_sock_bindtodevice(doc) ->
    [];
api_opt_sock_bindtodevice(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(api_opt_sock_bindtodevice,
           fun() -> has_support_sock_bindtodevice() end,
           fun() -> api_opt_sock_bindtodevice() end).


api_opt_sock_bindtodevice() ->
    Opt = bindtodevice,
    Set = fun(S, Val) ->
                  socket:setopt(S, socket, Opt, Val)
          end,
    Get = fun(S) ->
                  socket:getopt(S, socket, Opt)
          end,

    TesterSeq =
        [
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           case ?LIB:which_local_host_info(Domain) of
                               {ok, #{name := Name, addr := Addr}} ->
                                   ?SEV_IPRINT("local host info (~p): "
                                               "~n   Name: ~p"
                                               "~n   Addr: ~p",
                                               [Domain, Name, Addr]),
                                   LSA = #{family => Domain,
                                           addr   => Addr},
                                   {ok, State#{dev      => Name,
                                               local_sa => LSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "create UDP socket 1",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{usock1 => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "create UDP socket 2",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{usock2 => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "create TCP socket 1",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{tsock1 => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "create TCP socket 2",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{tsock2 => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "[get] verify UDP socket 1 (before bindtodevice)",
           cmd  => fun(#{usock1 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, enoprotoopt = Reason} ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p => SKIP",
					       [Reason]),
                                   {skip, Reason};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[get] verify UDP socket 2 (before bind)",
           cmd  => fun(#{usock2 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[get] verify TCP socket 1 (before bindtodevice)",
           cmd  => fun(#{tsock1 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[get] verify TCP socket 2 (before bind)",
           cmd  => fun(#{tsock2 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "Bind UDP socket 1 to device",
           cmd  => fun(#{usock1 := Sock, dev := Dev} = State) ->
                           case Set(Sock, Dev) of
                               ok ->
                                   ?SEV_IPRINT("Expected Success"),
                                   ok;
                               {error, eperm = Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   (catch socket:close(Sock)),
                                   {ok, State#{usock1 => skip}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Bind UDP socket 2 to local address",
           cmd  => fun(#{usock2 := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ?SEV_IPRINT("Expected Success"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Bind TCP socket 1 to device",
           cmd  => fun(#{usock1 := USock1,
                         tsock1 := Sock, dev := Dev} = State) ->
                           case Set(Sock, Dev) of
                               ok ->
                                   ?SEV_IPRINT("Expected Success"),
                                   ok;
                               {error, eperm = Reason} when (USock1 =:= skip) ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   {skip, Reason};
                               {error, eperm = Reason} ->
                                   ?SEV_IPRINT("Expected Failure: ~p", [Reason]),
                                   (catch socket:close(Sock)),
                                   {ok, State#{tsock1 => skip}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Bind TCP socket 2 to local address",
           cmd  => fun(#{tsock2 := Sock, local_sa := LSA} = _State) ->
                           case socket:bind(Sock, LSA) of
                               {ok, _Port} ->
                                   ?SEV_IPRINT("Expected Success"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "[get] verify UDP socket 1 (after bindtodevice)",
           cmd  => fun(#{usock1 := skip} = _State) ->
                           ?SEV_IPRINT("SKIP'ed (previous eperm)"),
                           ok;
                      (#{usock1 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[get] verify UDP socket 2 (after bind)",
           cmd  => fun(#{usock2 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[get] verify TCP socket 1 (after bindtodevice)",
           cmd  => fun(#{tsock1 := skip} = _State) ->
                           ?SEV_IPRINT("SKIP'ed (previous eperm)"),
                           ok;
                      (#{tsock1 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[get] verify TCP socket 2 (after bind)",
           cmd  => fun(#{tsock2 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Dev} ->
                                   ?SEV_IPRINT("Expected Success: ~p", [Dev]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]),
                                   ERROR
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         %% *** Termination ***
         #{desc => "close UDP socket 1",
           cmd  => fun(#{usock1 := skip} = State) ->
                           ?SEV_IPRINT("SKIP'ed (already closed)"),
                           {ok, maps:remove(usock1, State)};
                      (#{usock1 := Sock} = State) ->
                           socket:close(Sock),
                           {ok, maps:remove(usock1, State)}
                   end},
         #{desc => "close UDP socket 2",
           cmd  => fun(#{usock2 := Sock} = State) ->
                           socket:close(Sock),
                           {ok, maps:remove(usock2, State)}
                   end},
         #{desc => "close TCP socket 1",
           cmd  => fun(#{tsock1 := skip} = State) ->
                           ?SEV_IPRINT("SKIP'ed (already closed)"),
                           {ok, maps:remove(tsock1, State)};
                      (#{tsock1 := Sock} = State) ->
                           socket:close(Sock),
                           {ok, maps:remove(tsock1, State)}
                   end},
         #{desc => "close TCP socket 2",
           cmd  => fun(#{tsock2 := Sock} = State) ->
                           socket:close(Sock),
                           {ok, maps:remove(tsock2, State)}
                   end},

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

    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain  => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option broadcast.
%% Make it possible for datagram sockets to send packets to a broadcast
%% address (IPv4 only).

api_opt_sock_broadcast(suite) ->
    [];
api_opt_sock_broadcast(doc) ->
    [];
api_opt_sock_broadcast(_Config) when is_list(_Config) ->
    ?TT(?SECS(30)),
    tc_try(api_opt_sock_broadcast,
           fun() -> has_support_sock_broadcast() end,
           fun() -> api_opt_sock_broadcast() end).


api_opt_sock_broadcast() ->
    Opt    = broadcast,
    Set    = fun(S, Val) when is_boolean(Val) ->
                     socket:setopt(S, socket, Opt, Val)
             end,
    Get    = fun(S) ->
                     socket:getopt(S, socket, Opt)
             end,

    TesterSeq =
        [
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           case ?LIB:which_local_host_info(Domain) of
                               {ok, #{name      := Name,
                                      addr      := Addr,
                                      broadaddr := BAddr}} ->
                                   ?SEV_IPRINT("local host info: "
                                               "~n   Name:           ~p"
                                               "~n   Addr:           ~p"
                                               "~n   Broadcast Addr: ~p",
                                               [Name, Addr, BAddr]),
                                   LSA = #{family => Domain,
                                           addr   => Addr},
                                   BSA = #{family => Domain,
                                           addr   => BAddr},
                                   {ok, State#{lsa => LSA,
                                               bsa => BSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "[socket 1] create UDP socket (listening 1)",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock1 => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "[socket 1] Bind UDP socket (to limited broadcast address)",
           cmd  => fun(#{sock1 := Sock} = State) ->
			   BSA = #{family => inet,
				   addr   => broadcast},
                           ?SEV_IPRINT("Try bind (socket 1) to: "
                                       "~n   ~p", [BSA]),
                           case socket:bind(Sock, BSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("Expected Success (bound): ~p",
                                               [Port]),
                                   {ok, State#{sa1 => BSA#{port => Port}}};
                               {error, eaddrnotavail = Reason} ->
                                   ?SEV_IPRINT("~p => "
					       "SKIP limited broadcast test",
					       [Reason]),
                                   {ok, State#{sa1 => skip}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[socket 1] UDP socket sockname",
           cmd  => fun(#{sa1 := skip} = _State) ->
                           ?SEV_IPRINT("SKIP limited broadcast test"),
                           ok;
		      (#{sock1 := Sock} = _State) ->
			   case socket:sockname(Sock) of
			       {ok, SA} ->
				   ?SEV_IPRINT("SA: ~p", [SA]),
				   ok;
			       {error, _} = ERROR ->
				   ERROR
			   end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "[socket 2] create UDP socket (listening 2)",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock2 => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "[socket 2] Bind UDP socket (to subnet-directed broadcast address)",
           cmd  => fun(#{sock2 := Sock,
			 bsa   := BSA} = State) ->
                           ?SEV_IPRINT("Try bind (socket 1) to: "
                                       "~n   ~p", [BSA]),
                           case socket:bind(Sock, BSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("Expected Success (bound): ~p",
                                               [Port]),
                                   {ok, State#{sa2 => BSA#{port => Port}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[socket 2] UDP socket sockname",
           cmd  => fun(#{sock2 := Sock} = _State) ->
                           case socket:sockname(Sock) of
                               {ok, SA} ->
				   ?SEV_IPRINT("SA: ~p", [SA]),
                                   ok;
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "[socket 3] create UDP socket (sender)",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{sock3 => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "[socket 3][get] verify UDP socket (before bind and set)",
           cmd  => fun(#{sock3 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, false} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "broadcast not allowed"),
                                   ok;
                               {ok, true} ->
                                   ?SEV_IPRINT("Unexpected Success result: "
                                               "broadcast already allowed"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[socket 3] Try make broadcast allowed",
           cmd  => fun(#{sock3 := Sock} = _State) ->
                           case Set(Sock, true) of
                               ok ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "broadcast now allowed"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[socket 3] verify UDP socket broadcast allowed",
           cmd  => fun(#{sock3 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, true} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "broadcast allowed"),
                                   ok;
                               {ok, false} ->
                                   ?SEV_IPRINT("Unexpected Success result: "
                                               "broadcast *not* allowed"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[socket 3] Bind UDP socket (to local address)",
           cmd  => fun(#{sock3 := Sock, lsa := LSA} = State) ->
                           ?SEV_IPRINT("Try bind (socket 2) to: "
                                       "~n   ~p", [LSA]),
                           case socket:bind(Sock, LSA) of
                               {ok, Port} ->
                                   ?SEV_IPRINT("Expected Success (bound): ~p",
                                               [Port]),
                                   {ok, State#{sa3 => LSA#{port => Port}}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[socket 3] verify UDP socket (after set)",
           cmd  => fun(#{sock3 := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, true} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "broadcast allowed"),
                                   ok;
                               {ok, false} ->
                                   ?SEV_IPRINT("Unexpected Success result: "
                                               "broadcast not allowed"),
                                   {error, not_allowed};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},

	 ?SEV_SLEEP(?SECS(1)),

         #{desc => "[socket 3] try send to limited broadcast address",
           cmd  => fun(#{sa1 := skip} = _State) ->
                           ?SEV_IPRINT("SKIP limited broadcast test"),
			   ok;
		      (#{sock3 := Sock,
			 sa1   := Dest} = _State) ->
			   Data = list_to_binary("hejsan"),
			   ?SEV_IPRINT("try send to bradcast address: "
				       "~n   ~p", [Dest]),
			   case socket:sendto(Sock, Data, Dest) of
			       ok ->
				   ?SEV_IPRINT("Expected Success: "
					       "broadcast message sent"),
				   ok;
			       {error, Reason} = ERROR ->
				   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
				   ERROR
			   end
		   end},
         #{desc => "[socket 1] try recv",
           cmd  => fun(#{sa1 := skip} = _State) ->
			   ?SEV_IPRINT("SKIP limited broadcast test"),
			   ok;
		      (#{sock1 := Sock} = State) ->
                           case socket:recvfrom(Sock, 0, 5000) of
                               {ok, _} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "received message"),
                                   ok;
                               {error, timeout = Reason} ->
                                   %% Some platforms seem to balk at this.
                                   %% It spossible to bind to this, and
                                   %% send to it, but no data is received.
                                   %% At some point we should investigate...
                                   %% For now, we just skip this part of
                                   %% the test...
                                   ?SEV_IPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   {ok, State#{sa1 => skip}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},

	 ?SEV_SLEEP(?SECS(1)),

         #{desc => "[socket 3] try send to subnet-directed broadcast address",
           cmd  => fun(#{sock3 := Sock,
                         sa2   := Dest} = _State) ->
                           Data = list_to_binary("hejsan"),
                           ?SEV_IPRINT("try send to bradcast address: "
                                       "~n   ~p", [Dest]),
                           case socket:sendto(Sock, Data, Dest) of
                               ok ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "broadcast message sent"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "[socket 2] try recv",
           cmd  => fun(#{sock2 := Sock, sa1 := SA1} = _State) ->
                           case socket:recvfrom(Sock, 0, 5000) of
                               {ok, _} ->
                                   ?SEV_IPRINT("Expected Success: "
                                               "received message"),
                                   ok;
                               {error, timeout = Reason} when (SA1 =:= skip) ->
                                   ?SEV_IPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   {skip, "receive timeout"};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},

         %% *** Termination ***
         #{desc => "[socket 3] close UDP socket (sender)",
           cmd  => fun(#{sock3 := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(sock3, State0),
			   State2 = maps:remove(sa3,   State1),
			   {ok, State2}
                   end},
         #{desc => "[socket 2] close UDP socket (listener 2)",
           cmd  => fun(#{sock2 := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(sock2, State0),
			   State2 = maps:remove(sa2,   State1),
                           {ok, State2}
                   end},
         #{desc => "[socket 1] close UDP socket (listener 1)",
           cmd  => fun(#{sock1 := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(sock1, State0),
			   State2 = maps:remove(sa1,   State1),
                           {ok, State2}
                   end},

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

    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option debug.
%% On linux, this test requires that the user running the test to have
%% CAP_NET_ADMIN capabilities or be root (effective user ID of 0), 
%% therefor we explicitly test for the result eacces when attempting to
%% set, and skip if we get it.

api_opt_sock_debug(suite) ->
    [];
api_opt_sock_debug(doc) ->
    [];
api_opt_sock_debug(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_opt_sock_debug,
           fun() -> has_support_sock_debug() end,
           fun() -> api_opt_sock_debug() end).


api_opt_sock_debug() ->
    Opt    = debug,
    Set    = fun(S, Val) when is_integer(Val) ->
                     socket:setopt(S, socket, Opt, Val)
             end,
    Get    = fun(S) ->
                     socket:getopt(S, socket, Opt)
             end,

    TesterSeq =
        [
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           case ?LIB:which_local_host_info(Domain) of
                               {ok, #{name      := Name,
                                      addr      := Addr,
                                      broadaddr := BAddr}} ->
                                   ?SEV_IPRINT("local host info: "
                                               "~n   Name:           ~p"
                                               "~n   Addr:           ~p"
                                               "~n   Broadcast Addr: ~p",
                                               [Name, Addr, BAddr]),
                                   LSA = #{family => Domain,
                                           addr   => Addr},
                                   BSA = #{family => Domain,
                                           addr   => BAddr},
                                   {ok, State#{lsa => LSA,
                                               bsa => BSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "create UDP 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 => "Get current debug value",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock) of
                               {ok, Debug} when is_integer(Debug) ->
                                   ?SEV_IPRINT("Success: ~p", [Debug]),
                                   {ok, State#{debug => Debug}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Try enable socket debug",
           cmd  => fun(#{sock := Sock, debug := Debug} = State) ->
			   NewDebug = Debug + 1,
                           case Set(Sock, NewDebug) of
                               ok ->
                                   ?SEV_IPRINT("Expected Success"),
                                   {ok, State#{debug => NewDebug}};
                               {error, eacces = Reason} ->
                                   ?SEV_EPRINT("NO ACCESS => SKIP"),
                                   {skip, Reason};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Get current (new) debug value",
           cmd  => fun(#{sock := Sock, debug := Debug} = _State) ->
                           case Get(Sock) of
                               {ok, Debug} when is_integer(Debug) ->
                                   ?SEV_IPRINT("Success: ~p", [Debug]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},

         %% *** Termination ***
         #{desc => "close UDP socket",
           cmd  => fun(#{sock := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(sock, State0),
                           {ok, State1}
                   end},

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

    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option domain.
%% This is a read only option. Also not available on all platforms.

api_opt_sock_domain(suite) ->
    [];
api_opt_sock_domain(doc) ->
    [];
api_opt_sock_domain(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_opt_sock_domain,
           fun() -> has_support_sock_domain() end,
           fun() -> api_opt_sock_domain() end).


api_opt_sock_domain() ->
    Opt = domain,
    Get = fun(S) ->
                  socket:getopt(S, socket, Opt)
          end,

    TesterSeq =
        [
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           case ?LIB:which_local_host_info(Domain) of
                               {ok, #{name      := Name,
                                      addr      := Addr,
                                      broadaddr := BAddr}} ->
                                   ?SEV_IPRINT("local host info: "
                                               "~n   Name:           ~p"
                                               "~n   Addr:           ~p"
                                               "~n   Broadcast Addr: ~p",
                                               [Name, Addr, BAddr]),
                                   LSA = #{family => Domain,
                                           addr   => Addr},
                                   BSA = #{family => Domain,
                                           addr   => BAddr},
                                   {ok, State#{lsa => LSA,
                                               bsa => BSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "create IPv4 UDP socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, dgram, udp) of
                               {ok, Sock} ->
                                   {ok, State#{usock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "Get domain for the UDP socket",
           cmd  => fun(#{domain := Domain, usock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Domain} ->
                                   ?SEV_IPRINT("Success: ~p", [Domain]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "create TCP socket",
           cmd  => fun(#{domain := Domain} = State) ->
                           case socket:open(Domain, stream, tcp) of
                               {ok, Sock} ->
                                   {ok, State#{tsock => Sock}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "Get domain for the TCP socket",
           cmd  => fun(#{domain := Domain, tsock := Sock} = _State) ->
                           case Get(Sock) of
                               {ok, Domain} ->
                                   ?SEV_IPRINT("Success: ~p", [Domain]),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},

         %% *** Termination ***
         #{desc => "close UDP socket",
           cmd  => fun(#{usock := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(usock, State0),
                           {ok, State1}
                   end},
         #{desc => "close TCP socket",
           cmd  => fun(#{tsock := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(tsock, State0),
                           {ok, State1}
                   end},

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

    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option dontroute.
%% The man page has the following to say:
%% "Don't send via a gateway, send only to directly connected hosts.
%%  The same effect can be achieved by setting the MSG_DONTROUTE
%%  flag on a socket send(2) operation."
%% Since its "kind of" difficult to check if it actually takes an 
%% effect (you would need a gateway for that and a machine "on the
%% other side"), we only test if we can set and get the value.
%% Better then nothing.

api_opt_sock_dontroute(suite) ->
    [];
api_opt_sock_dontroute(doc) ->
    [];
api_opt_sock_dontroute(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_opt_sock_dontroute,
           fun() -> has_support_sock_dontroute() end,
           fun() -> api_opt_sock_dontroute() end).


api_opt_sock_dontroute() ->
    Opt    = dontroute,
    Set    = fun(S, Val) when is_boolean(Val) ->
                     socket:setopt(S, socket, Opt, Val)
             end,
    Get    = fun(S) ->
                     socket:getopt(S, socket, Opt)
             end,

    TesterSeq =
        [
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           case ?LIB:which_local_host_info(Domain) of
                               {ok, #{name      := Name,
                                      addr      := Addr,
                                      broadaddr := BAddr}} ->
                                   ?SEV_IPRINT("local host info: "
                                               "~n   Name:           ~p"
                                               "~n   Addr:           ~p"
                                               "~n   Broadcast Addr: ~p",
                                               [Name, Addr, BAddr]),
                                   LSA = #{family => Domain,
                                           addr   => Addr},
                                   BSA = #{family => Domain,
                                           addr   => BAddr},
                                   {ok, State#{lsa => LSA,
                                               bsa => BSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "create UDP 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 => "Get current value",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock) of
                               {ok, Val} when is_boolean(Val) ->
                                   ?SEV_IPRINT("Success: ~p", [Val]),
                                   {ok, State#{dontroute => Val}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Try change value",
           cmd  => fun(#{sock := Sock, dontroute := Current} = State) ->
			   New = not Current,
                           ?SEV_IPRINT("Change from ~p to ~p", [Current, New]),
                           case Set(Sock, New) of
                               ok ->
                                   ?SEV_IPRINT("Expected Success"),
                                   {ok, State#{dontroute => New}};
                               {error, eopnotsupp = Reason} ->
                                   ?SEV_EPRINT("Expected Failure: ~p",
					       [Reason]),
                                   {skip, Reason};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Verify changed value",
           cmd  => fun(#{sock := Sock, dontroute := Val} = _State) ->
                           case Get(Sock) of
                               {ok, Val} ->
                                   ?SEV_IPRINT("Expected Success"),
                                   ok;
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},

         %% *** Termination ***
         #{desc => "close UDP socket",
           cmd  => fun(#{sock := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(sock, State0),
                           {ok, State1}
                   end},

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

    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option error. PLACEHOLDER!

api_opt_sock_error(suite) ->
    [];
api_opt_sock_error(doc) ->
    [];
api_opt_sock_error(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_opt_sock_error,
           fun() -> not_yet_implemented() end,
           fun() -> ok end).



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

%% Tests the socket option keepalive.
%% This is bit tricky to test, partly because we have no control over
%% the underlying TCP timeouts. So, for now, we just test that we can
%% change the value.

api_opt_sock_keepalive(suite) ->
    [];
api_opt_sock_keepalive(doc) ->
    [];
api_opt_sock_keepalive(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_opt_sock_keepalive,
           fun() -> has_support_sock_keepalive() end,
           fun() -> api_opt_sock_keepalive() end).


api_opt_sock_keepalive() ->
    Opt    = keepalive,
    Set    = fun(S, Val) when is_boolean(Val) ->
                     socket:setopt(S, socket, Opt, Val)
             end,
    Get    = fun(S) ->
                     socket:getopt(S, socket, Opt)
             end,

    TesterSeq =
        [
         #{desc => "which local address",
           cmd  => fun(#{domain := Domain} = State) ->
                           case ?LIB:which_local_host_info(Domain) of
                               {ok, #{name      := Name,
                                      addr      := Addr,
                                      broadaddr := BAddr}} ->
                                   ?SEV_IPRINT("local host info: "
                                               "~n   Name:           ~p"
                                               "~n   Addr:           ~p"
                                               "~n   Broadcast Addr: ~p",
                                               [Name, Addr, BAddr]),
                                   LSA = #{family => Domain,
                                           addr   => Addr},
                                   BSA = #{family => Domain,
                                           addr   => BAddr},
                                   {ok, State#{lsa => LSA,
                                               bsa => BSA}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},

         #{desc => "create TCP 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 => "Get current value",
           cmd  => fun(#{sock := Sock} = State) ->
                           case Get(Sock) of
                               {ok, Val} when is_boolean(Val) ->
                                   ?SEV_IPRINT("Success: ~p", [Val]),
                                   {ok, State#{keepalive => Val}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Try change the value",
           cmd  => fun(#{sock := Sock, keepalive := Current} = State) ->
			   New = not Current,
                           ?SEV_IPRINT("Try change value from ~p to ~p", 
                                       [Current, New]),
                           case Set(Sock, New) of
                               ok ->
                                   ?SEV_IPRINT("Expected Success"),
                                   {ok, State#{keepalive => New}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected Failure: ~p",
					       [Reason]),
                                   ERROR
                           end
                   end},
         #{desc => "Verify (new) current value",
           cmd  => fun(#{sock := Sock, keepalive := Val} = _State) ->
                           case Get(Sock) of
                               {ok, Val} ->
                                   ?SEV_IPRINT("Expected Success (~p)", [Val]),
                                   ok;
                               {ok, OtherVal} ->
                                   ?SEV_IPRINT("Unexpected Success: ~p",
                                               [OtherVal]),
                                   {error, {unexpected_success_value,
                                            Val, OtherVal}};
                               {error, Reason} = ERROR ->
                                   ?SEV_EPRINT("Unexpected failure: ~p",
                                               [Reason]),
                                   ERROR
                           end
                   end},

         %% *** Termination ***
         #{desc => "close UDP socket",
           cmd  => fun(#{sock := Sock} = State0) ->
                           socket:close(Sock),
			   State1 = maps:remove(sock, State0),
                           {ok, State1}
                   end},

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

    Domain = inet,

    i("start tester evaluator"),
    InitState = #{domain => Domain},
    Tester = ?SEV_START("tester", TesterSeq, InitState),

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



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

%% Tests the socket option linger. PLACEHOLDER!

api_opt_sock_linger(suite) ->
    [];
api_opt_sock_linger(doc) ->
    [];
api_opt_sock_linger(_Config) when is_list(_Config) ->
    ?TT(?SECS(10)),
    tc_try(api_opt_sock_linger,
           fun() -> not_yet_implemented() end,
           fun() -> ok end).



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

%% 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_support_ip_add_membership(),
                   has_support_ip_drop_membership(),
                   has_support_ip_multicast()
           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
        ],


    Domain = inet,
    i("get multicast address"),
    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 ->
            %% Actually, what is "not supported". is netstat!
            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),
    %% On some platforms the netstat barfs out some crap on stderr
    %% before the actual info...
    case os:cmd("netstat -g 2>/dev/null | grep " ++ IfName) of
        [] ->
            %% Can't figure out if we support multicast or not...
            not_supported(no_netstat);
        NetstatGroupsStr ->
            try
                begin
                    NetstatGroups0   = string:tokens(NetstatGroupsStr, [$\n]),
                    NetstatGroups    = [string:tokens(G, [$ ]) || 
                                           G <- NetstatGroups0],
                    MAddrs           = [WhichMAddr(NetstatGroup) || 
                                           NetstatGroup <- NetstatGroups],
                    which_multicast_address3(Domain, MAddrs)
                end
            catch
                throw:E:_ ->
                    throw(E);
                C:E:S ->
                    not_supported({multicast, {C,E,S}})
            end
    end.

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 ?LIB:which_local_host_info(Domain) of
        {ok, #{name := Name}} ->
            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() -> has_support_ipv6() end,
           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() -> has_support_ipv6() end,
           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() -> has_support_ipv6() end,
           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() -> has_support_ipv6() end,
           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(30)),
    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(30)),
    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(30)),
    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(30)),
    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(30)),
    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(30)),
    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},

         ?SEV_SLEEP(?SECS(5)),

         %% 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.
         %% Note that its still a race that the nif has processed that the
         %% "controlling process" has terminated. There really is no 
         %% proper timeout for this, but the 5 seconds "should" be enough...
         %% We should really have some way to subscribe to socket events...
         #{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 (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv4.

traffic_send_and_recv_counters_tcp4(suite) ->
    [];
traffic_send_and_recv_counters_tcp4(doc) ->
    [];
traffic_send_and_recv_counters_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_send_and_recv_counters_tcp4,
           fun() ->
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 recv   => fun(S)    -> socket:recv(S)    end,
                                 send   => fun(S, D) -> socket:send(S, D) end},
                   ok = traffic_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv6.

traffic_send_and_recv_counters_tcp6(suite) ->
    [];
traffic_send_and_recv_counters_tcp6(doc) ->
    [];
traffic_send_and_recv_counters_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_send_and_recv_counters_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 recv   => fun(S)    -> socket:recv(S)    end,
                                 send   => fun(S, D) -> socket:send(S, D) end},
                   ok = traffic_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use default (TCP) on local.

traffic_send_and_recv_counters_tcpL(suite) ->
    [];
traffic_send_and_recv_counters_tcpL(doc) ->
    [];
traffic_send_and_recv_counters_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_send_and_recv_counters_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 recv   => fun(S)    -> socket:recv(S)    end,
                                 send   => fun(S, D) -> socket:send(S, D) end},
                   ok = traffic_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv4.

traffic_sendmsg_and_recvmsg_counters_tcp4(suite) ->
    [];
traffic_sendmsg_and_recvmsg_counters_tcp4(doc) ->
    [];
traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendmsg_and_recvmsg_counters_tcp4,
           fun() ->
                   InitState = #{domain => inet,
                                 proto  => tcp,
                                 recv   => fun(S) ->
                                                   case socket:recvmsg(S) of
                                                       {ok, #{addr := _Source,
                                                              iov  := [Data]}} ->
                                                           {ok, Data};
                                                       {error, _} = ERROR ->
                                                           ERROR
                                                   end
                                           end,
                                 send   => fun(S, Data) ->
                                                   MsgHdr = #{iov => [Data]},
                                                   socket:sendmsg(S, MsgHdr)
                                           end},
                   ok = traffic_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv6.

traffic_sendmsg_and_recvmsg_counters_tcp6(suite) ->
    [];
traffic_sendmsg_and_recvmsg_counters_tcp6(doc) ->
    [];
traffic_sendmsg_and_recvmsg_counters_tcp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendmsg_and_recvmsg_counters_tcp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6,
                                 proto  => tcp,
                                 recv   => fun(S) ->
                                                   case socket:recvmsg(S) of
                                                       {ok, #{addr := _Source,
                                                              iov  := [Data]}} ->
                                                           {ok, Data};
                                                       {error, _} = ERROR ->
                                                           ERROR
                                                   end
                                           end,
                                 send   => fun(S, Data) ->
                                                   MsgHdr = #{iov => [Data]},
                                                   socket:sendmsg(S, MsgHdr)
                                           end},
                   ok = traffic_send_and_recv_tcp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use default (TCP) on local.

traffic_sendmsg_and_recvmsg_counters_tcpL(suite) ->
    [];
traffic_sendmsg_and_recvmsg_counters_tcpL(doc) ->
    [];
traffic_sendmsg_and_recvmsg_counters_tcpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendmsg_and_recvmsg_counters_tcpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 recv   => fun(S) ->
                                                   case socket:recvmsg(S) of
                                                       {ok, #{addr := _Source,
                                                              iov  := [Data]}} ->
                                                           {ok, Data};
                                                       {error, _} = ERROR ->
                                                           ERROR
                                                   end
                                           end,
                                 send   => fun(S, Data) ->
                                                   MsgHdr = #{iov => [Data]},
                                                   socket:sendmsg(S, MsgHdr)
                                           end},
                   ok = traffic_send_and_recv_tcp(InitState)
           end).


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

traffic_send_and_recv_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, eafnosupport = Reason} ->
                                   {skip, Reason};
                               {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 := #{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) ->
                           ?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 => "initial counter validation (=zero)",
           cmd  => fun(#{csock := Sock} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("Validate initial counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(Counters)
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (accept)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, accept),
                           ok
                   end},

         #{desc => "await continue (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (1)",
           cmd  => fun(#{csock := Sock,
                         recv  := Recv} = State) ->
                           case Recv(Sock) of
                               {ok, Data} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => 1,
                                               read_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 1)",
           cmd  => fun(#{csock     := Sock,
                         read_pkg  := Pkg,
                         read_byte := Byte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,   Pkg},
                                      {read_byte,  Byte},
                                      {read_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           ok
                   end},

         #{desc => "await continue (send_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (1)",
           cmd  => fun(#{csock := Sock,
                         send  := Send} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => 1,
                                               write_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 1)",
           cmd  => fun(#{csock      := Sock,
                         read_pkg   := RPkg,
                         read_byte  := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           ok
                   end},

         #{desc => "await continue (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (2)",
           cmd  => fun(#{csock     := Sock,
                         recv      := Recv,
                         read_pkg  := Pkg,
                         read_byte := Byte} = State) ->
                           case Recv(Sock) of
                               {ok, Data} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => Pkg + 1,
                                               read_byte => Byte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 2)",
           cmd  => fun(#{csock      := Sock,
                         read_pkg   := RPkg,
                         read_byte  := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           ok
                   end},

         #{desc => "await continue (send_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (2)",
           cmd  => fun(#{csock      := Sock,
                         send       := Send,
                         write_pkg  := Pkg,
                         write_byte := Byte} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => Pkg + 1,
                                               write_byte => Byte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 2)",
           cmd  => fun(#{csock      := Sock,
                         read_pkg   := RPkg,
                         read_byte  := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           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 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 (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} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** 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, eafnosupport = Reason} ->
                                   {skip, Reason};
                               {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),
                           ok
                   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_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (1)",
           cmd  => fun(#{sock := Sock,
                         send := Send} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => 1,
                                               write_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 1)",
           cmd  => fun(#{sock      := Sock,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           ok
                   end},

         #{desc => "await continue (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (1)",
           cmd  => fun(#{sock := Sock,
                         recv := Recv} = State) ->
                           case Recv(Sock) of
                               {ok, Data} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => 1,
                                               read_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 1)",
           cmd  => fun(#{sock      := Sock,
                         read_pkg  := RPkg,
                         read_byte := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           ok
                   end},

         #{desc => "await continue (send_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (2)",
           cmd  => fun(#{sock       := Sock,
                         send       := Send,
                         write_pkg  := SPkg,
                         write_byte := SByte} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => SPkg + 1,
                                               write_byte => SByte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 2)",
           cmd  => fun(#{sock      := Sock,
                         read_pkg  := RPkg,
                         read_byte := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           ok
                   end},

         #{desc => "await continue (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (2)",
           cmd  => fun(#{sock      := Sock,
                         recv      := Recv,
                         read_pkg  := RPkg,
                         read_byte := RByte} = State) ->
                           case Recv(Sock) of
                               {ok, Data} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => RPkg + 1,
                                               read_byte => RByte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 2)",
           cmd  => fun(#{sock      := Sock,
                         read_pkg  := RPkg,
                         read_byte := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           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 connection 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) ->
                           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(#{domain := local,
                         server := Pid} = State) ->
                           {ok, Path} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{path => Path}};
                      (#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{port => Port}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{domain := local,
                         client := Pid,
                         path   := Path} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Path),
                           ok;
                      (#{client := Pid,
                         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},

         ?SEV_SLEEP(?SECS(1)),

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

         ?SEV_SLEEP(?SECS(1)),

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

         ?SEV_SLEEP(?SECS(1)),

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

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "order client to continue (recv_and_validate 2)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, recv_and_validate),
                           ok
                   end},
         #{desc => "order server to continue (send_and_validate 2)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, send_and_validate),
                           ok
                   end},
         #{desc => "await server ready (send_and_validate 2)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, send_and_validate)
                   end},
         #{desc => "await client ready (recv_and_validate 2)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, recv_and_validate)
                   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"),
    ServerInitState = InitState#{host => local_host()},
    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_sar_counters_validation(Counters) ->
    traffic_sar_counters_validation(Counters, []).

traffic_sar_counters_validation(Counters, []) ->
    (catch lists:foreach(
             fun({_Cnt, 0})   -> ok;
                ({Cnt,  Val}) -> throw({error, {invalid_counter, Cnt, Val}})
             end,
             Counters));
traffic_sar_counters_validation(Counters, [{Cnt, Val}|ValidateCounters]) ->
    case lists:keysearch(Cnt, 1, Counters) of
        {value, {Cnt, Val}} ->
            Counters2 = lists:keydelete(Cnt, 1, Counters),
            traffic_sar_counters_validation(Counters2, ValidateCounters);
        {value, {Cnt, _Val}} when (Val =:= any) ->
            Counters2 = lists:keydelete(Cnt, 1, Counters),
            traffic_sar_counters_validation(Counters2, ValidateCounters);
        {value, {Cnt, InvVal}} ->
            {error, {invalid_counter, Cnt, InvVal, Val}};
        false ->
            {error, {unknown_counter, Cnt, Counters}}
    end.

                          

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv4.

traffic_sendto_and_recvfrom_counters_udp4(suite) ->
    [];
traffic_sendto_and_recvfrom_counters_udp4(doc) ->
    [];
traffic_sendto_and_recvfrom_counters_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendto_and_recvfrom_counters_udp4,
           fun() ->
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 recv   => fun(S) ->
                                                   socket:recvfrom(S)
                                           end,
                                 send   => fun(S, Data, Dest) ->
                                                   socket:sendto(S, Data, Dest)
                                           end},
                   ok = traffic_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv6.

traffic_sendto_and_recvfrom_counters_udp6(suite) ->
    [];
traffic_sendto_and_recvfrom_counters_udp6(doc) ->
    [];
traffic_sendto_and_recvfrom_counters_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendto_and_recvfrom_counters_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6,
                                 proto  => udp,
                                 recv   => fun(S) ->
                                                   socket:recvfrom(S)
                                           end,
                                 send   => fun(S, Data, Dest) ->
                                                   socket:sendto(S, Data, Dest)
                                           end},
                   ok = traffic_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use default (UDP) on local.

traffic_sendto_and_recvfrom_counters_udpL(suite) ->
    [];
traffic_sendto_and_recvfrom_counters_udpL(doc) ->
    [];
traffic_sendto_and_recvfrom_counters_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendto_and_recvfrom_counters_udp4,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 recv   => fun(S) ->
                                                   socket:recvfrom(S)
                                           end,
                                 send   => fun(S, Data, Dest) ->
                                                   socket:sendto(S, Data, Dest)
                                           end},
                   ok = traffic_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv4.

traffic_sendmsg_and_recvmsg_counters_udp4(suite) ->
    [];
traffic_sendmsg_and_recvmsg_counters_udp4(doc) ->
    [];
traffic_sendmsg_and_recvmsg_counters_udp4(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendmsg_and_recvmsg_counters_udp4,
           fun() ->
                   InitState = #{domain => inet,
                                 proto  => udp,
                                 recv   => fun(S) ->
                                                   case socket:recvmsg(S) of
                                                       {ok, #{addr  := Source,
                                                              iov   := [Data]}} ->
                                                           {ok, {Source, Data}};
                                                       {error, _} = ERROR ->
                                                           ERROR
                                                   end
                                           end,
                                 send   => fun(S, Data, Dest) ->
                                                   MsgHdr = #{addr => Dest,
                                                              iov  => [Data]},
                                                   socket:sendmsg(S, MsgHdr)
                                           end},
                   ok = traffic_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv6.

traffic_sendmsg_and_recvmsg_counters_udp6(suite) ->
    [];
traffic_sendmsg_and_recvmsg_counters_udp6(doc) ->
    [];
traffic_sendmsg_and_recvmsg_counters_udp6(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendmsg_and_recvmsg_counters_udp6,
           fun() -> has_support_ipv6() end,
           fun() ->
                   InitState = #{domain => inet6,
                                 proto  => udp,
                                 recv   => fun(S) ->
                                                   case socket:recvmsg(S) of
                                                       {ok, #{addr  := Source,
                                                              iov   := [Data]}} ->
                                                           {ok, {Source, Data}};
                                                       {error, _} = ERROR ->
                                                           ERROR
                                                   end
                                           end,
                                 send   => fun(S, Data, Dest) ->
                                                   MsgHdr = #{addr => Dest,
                                                              iov  => [Data]},
                                                   socket:sendmsg(S, MsgHdr)
                                           end},
                   ok = traffic_send_and_recv_udp(InitState)
           end).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case is intended to (simply) test that the counters
%% for both read and write.
%% So that its easy to extend, we use fun's for read and write.
%% We use default (UDP) on local.

traffic_sendmsg_and_recvmsg_counters_udpL(suite) ->
    [];
traffic_sendmsg_and_recvmsg_counters_udpL(doc) ->
    [];
traffic_sendmsg_and_recvmsg_counters_udpL(_Config) when is_list(_Config) ->
    ?TT(?SECS(15)),
    tc_try(traffic_sendmsg_and_recvmsg_counters_udpL,
           fun() -> has_support_unix_domain_socket() end,
           fun() ->
                   InitState = #{domain => local,
                                 proto  => default,
                                 recv   => fun(S) ->
                                                   case socket:recvmsg(S) of
                                                       {ok, #{addr  := Source,
                                                              iov   := [Data]}} ->
                                                           {ok, {Source, Data}};
                                                       {error, _} = ERROR ->
                                                           ERROR
                                                   end
                                           end,
                                 send   => fun(S, Data, Dest) ->
                                                   MsgHdr = #{addr => Dest,
                                                              iov  => [Data]},
                                                   socket:sendmsg(S, MsgHdr)
                                           end},
                   ok = traffic_send_and_recv_udp(InitState)
           end).


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

traffic_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, 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, _Port} ->
                                   ok; % We do not care about the port for local
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{sock     := LSock,
                         local_sa := LSA} = State) ->
                           case socket:bind(LSock, LSA) of
                               {ok, Port} ->
                                   {ok, State#{lport => Port}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "initial counter validation (=zero)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("Validate initial counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(Counters)
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{domain   := local,
                         tester   := Tester,
                         local_sa := #{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 (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (1)",
           cmd  => fun(#{sock := Sock,
                         recv := Recv} = State) ->
                           case Recv(Sock) of
                               {ok, {ClientSA, Data}} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{client_sa => ClientSA,
                                               read_pkg  => 1,
                                               read_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 1)",
           cmd  => fun(#{sock      := Sock,
                         read_pkg  := Pkg,
                         read_byte := Byte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,   Pkg},
                                      {read_byte,  Byte},
                                      {read_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           ok
                   end},

         #{desc => "await continue (send_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (1)",
           cmd  => fun(#{sock      := Sock,
                         send      := Send,
                         client_sa := ClientSA} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data, ClientSA) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => 1,
                                               write_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 1)",
           cmd  => fun(#{sock       := Sock,
                         read_pkg   := RPkg,
                         read_byte  := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           ok
                   end},

         #{desc => "await continue (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (2)",
           cmd  => fun(#{sock      := Sock,
                         recv      := Recv,
                         read_pkg  := Pkg,
                         read_byte := Byte} = State) ->
                           case Recv(Sock) of
                               {ok, {Source, Data}} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{client_sa => Source,
                                               read_pkg  => Pkg + 1,
                                               read_byte => Byte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 2)",
           cmd  => fun(#{sock       := Sock,
                         read_pkg   := RPkg,
                         read_byte  := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           ok
                   end},

         #{desc => "await continue (send_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (2)",
           cmd  => fun(#{sock       := Sock,
                         client_sa  := ClientSA,
                         send       := Send,
                         write_pkg  := Pkg,
                         write_byte := Byte} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data, ClientSA) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => Pkg + 1,
                                               write_byte => Byte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 2)",
           cmd  => fun(#{sock       := Sock,
                         read_pkg   := RPkg,
                         read_byte  := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           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 (just in case)",
           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(lsock, State1)};
                      (#{sock := Sock} = State) ->
                           (catch socket:close(Sock)),
                           {ok, maps:remove(sock, State)}
                   end},

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

    ClientSeq =
        [
         %% *** Wait for start order part ***
         #{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} = _State) ->
                           _MRef = erlang:monitor(process, Tester),
                           ok
                   end},

         %% *** 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, dgram, 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 => "initial counter validation (=zero)",
           cmd  => fun(#{sock := Sock} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("Validate initial counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(Counters)
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (init)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, init),
                           ok
                   end},

         %% The actual test
         #{desc => "await continue (send_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (1)",
           cmd  => fun(#{sock      := Sock,
                         send      := Send,
                         server_sa := ServerSA} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data, ServerSA) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => 1,
                                               write_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 1)",
           cmd  => fun(#{sock       := Sock,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           ok
                   end},

         #{desc => "await continue (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (1)",
           cmd  => fun(#{sock      := Sock,
                         recv      := Recv,
                         server_sa := #{family := local} = ServerSA} = State) ->
                           case Recv(Sock) of
                               {ok, {ServerSA, Data}} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => 1,
                                               read_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end;
                      (#{sock      := Sock,
                         recv      := Recv,
                         server_sa := #{addr := Addr, port := Port}} = State) ->
                           case Recv(Sock) of
                               {ok, {#{addr := Addr, port := Port}, Data}} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => 1,
                                               read_byte => size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 1)",
           cmd  => fun(#{sock      := Sock,
                         read_pkg  := RPkg,
                         read_byte := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 1)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           ok
                   end},

         #{desc => "await continue (send_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, send_and_validate)
                   end},
         #{desc => "send (2)",
           cmd  => fun(#{sock       := Sock,
                         send       := Send,
                         server_sa  := ServerSA,
                         write_pkg  := SPkg,
                         write_byte := SByte} = State) ->
                           Data = ?DATA,
                           case Send(Sock, Data, ServerSA) of
                               ok ->
                                   ?SEV_IPRINT("sent ~p bytes", [size(Data)]),
                                   {ok, State#{write_pkg  => SPkg + 1,
                                               write_byte => SByte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (send 2)",
           cmd  => fun(#{sock       := Sock,
                         read_pkg   := RPkg,
                         read_byte  := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (send_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, send_and_validate),
                           ok
                   end},

         #{desc => "await continue (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester} = _State) ->
                           ?SEV_AWAIT_CONTINUE(Tester, tester, recv_and_validate)
                   end},
         #{desc => "recv (2)",
           cmd  => fun(#{sock      := Sock,
                         server_sa := #{family := local} = ServerSA,
                         recv      := Recv,
                         read_pkg  := RPkg,
                         read_byte := RByte} = State) ->
                           case Recv(Sock) of
                               {ok, {ServerSA, Data}} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => RPkg + 1,
                                               read_byte => RByte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end;
		      (#{sock      := Sock,
                         server_sa := #{addr := Addr, port := Port},
                         recv      := Recv,
                         read_pkg  := RPkg,
                         read_byte := RByte} = State) ->
                           case Recv(Sock) of
                               {ok, {#{addr := Addr, port := Port}, Data}} ->
                                   ?SEV_IPRINT("recv ~p bytes", [size(Data)]),
                                   {ok, State#{read_pkg  => RPkg + 1,
                                               read_byte => RByte + size(Data)}};
                               {error, _} = ERROR ->
                                   ERROR
                           end
                   end},
         #{desc => "validate (recv 2)",
           cmd  => fun(#{sock      := Sock,
                         read_pkg  := RPkg,
                         read_byte := RByte,
                         write_pkg  := SPkg,
                         write_byte := SByte} = _State) ->
                           try socket:info(Sock) of
                               #{counters := Counters} ->
                                   ?SEV_IPRINT("validate counters: "
                                               "~n   ~p", [Counters]),
                                   traffic_sar_counters_validation(
                                     Counters,
                                     [{read_pkg,    RPkg},
                                      {read_byte,   RByte},
                                      {write_pkg,   SPkg},
                                      {write_byte,  SByte},
                                      {read_tries,  any},
                                      {write_tries, any}])
                           catch
                               C:E:S ->
                                   ?SEV_EPRINT("Failed get socket info: "
                                               "~n   Class: ~p"
                                               "~n   Error: ~p"
                                               "~n   Stack: ~p", [C, E, S]),
                                   {error, {socket_info_failed, {C, E, S}}}
                           end
                   end},
         #{desc => "announce ready (recv_and_validate 2)",
           cmd  => fun(#{tester := Tester}) ->
                           ?SEV_ANNOUNCE_READY(Tester, recv_and_validate),
                           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 connection 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) ->
                           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(#{domain := local,
                         server := Pid} = State) ->
                           {ok, Path} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{path => Path}};
                      (#{server := Pid} = State) ->
                           {ok, Port} = ?SEV_AWAIT_READY(Pid, server, init),
                           {ok, State#{port => Port}}
                   end},

         %% Start the client
         #{desc => "order client start",
           cmd  => fun(#{domain := local,
                         client := Pid,
                         path   := Path} = _State) ->
                           ?SEV_ANNOUNCE_START(Pid, Path),
                           ok;
                      (#{client := Pid,
                         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 (recv_and_validate 1)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, recv_and_validate),
                           ok
                   end},
         #{desc => "order client to continue (send_and_validate 1)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, send_and_validate),
                           ok
                   end},
         #{desc => "await client ready (send_and_validate 1)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, send_and_validate)
                   end},
         #{desc => "await server ready (recv_and_validate 1)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, recv_and_validate)
                   end},

         ?SEV_SLEEP(?SECS(1)),

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

         ?SEV_SLEEP(?SECS(1)),

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

         ?SEV_SLEEP(?SECS(1)),

         #{desc => "order client to continue (recv_and_validate 2)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Client, recv_and_validate),
                           ok
                   end},
         #{desc => "order server to continue (send_and_validate 2)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_ANNOUNCE_CONTINUE(Server, send_and_validate),
                           ok
                   end},
         #{desc => "await server ready (send_and_validate 2)",
           cmd  => fun(#{server := Server} = _State) ->
                           ?SEV_AWAIT_READY(Server, server, send_and_validate)
                   end},
         #{desc => "await client ready (recv_and_validate 2)",
           cmd  => fun(#{client := Client} = _State) ->
                           ?SEV_AWAIT_READY(Client, client, recv_and_validate)
                   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"),
    ServerInitState = InitState#{host => local_host()},
    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]).




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 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) ->
    Msg = l2b(?TPP_SMALL),
    Num = ?TPP_SMALL_NUM,
    tc_try(traffic_ping_pong_small_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 '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) ->
    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() ->
                   ?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 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(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 '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(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), 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(60)),
                   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(60)),
                   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(60)),
                   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(60)),
                   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(60)),
                   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(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 '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(60)),
                   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(60)),
                   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)) ->
                          NewRcvSz = 1024+size(Msg),
                          case socket:setopt(Sock, socket, rcvbuf, NewRcvSz) of
			      ok ->
				  ok;
			      {error, enobufs} ->
				  skip(?F("Change ~w buffer size (to ~w) "
                                          "not allowed", 
                                          [rcvbuf, NewRcvSz]));
			      {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)) ->
                          NewSndSz = 1024+size(Msg),
                          case socket:setopt(Sock, socket, sndbuf, NewSndSz) of
			      ok ->
				  ok;
			      {error, enobufs} ->
				  skip(?F("Change ~w buffer size (to ~w) "
                                          "not allowed", 
                                          [sndbuf, NewSndSz]));
			      {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,
					 #{family := local} = 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_client_handler_msg_exchange_loop(Sock,
					 #{addr := Addr, port := Port} = Dest0,
					 Send, Recv, Data,
                                         Num, N, Sent, Received, Start) ->
    case tpp_udp_send_req(Sock, Send, Data, Dest0) of
        {ok, SendSz} ->
            case tpp_udp_recv_rep(Sock, Recv) of
                {ok, NewData, RecvSz, #{addr := Addr, port := Port} = Dest1} ->
                    tpp_udp_client_handler_msg_exchange_loop(Sock, Dest1,
                                                             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
        ],

    Domain = maps:get(domain, InitState),
    LHost  = local_host(),
    LAddr  = which_local_addr(Domain),

    i("start server evaluator"),
    ServerInitState = #{host   => LHost,
			addr   => LAddr,
                        domain => Domain,
                        mod    => maps:get(server_mod,    InitState),
                        active => maps:get(server_active, InitState)},
    Server          = ?SEV_START("server", ServerSeq, ServerInitState),

    i("start client evaluator"),
    ClientInitState = #{host            => LHost,
			addr            => LAddr,
                        domain          => Domain,
                        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        => Domain,
			msg_id        => maps:get(msg_id,        InitState),
                        client        => Client#ev.pid,
			client_mod    => maps:get(client_mod,    InitState),
			client_active => maps:get(client_active, InitState),
                        server        => Server#ev.pid,
                        server_mod    => maps:get(server_mod,    InitState),
                        server_active => maps:get(server_active, InitState)},
    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) ->
    TransportMod = socket_test_ttest_tcp_gen,
    Transport    = {TransportMod, #{domain => Domain}},
    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) ->
    TransportMod = socket_test_ttest_tcp_gen,
    Transport    = {TransportMod, #{domain => Domain}},    
    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_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 socket 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 ?LIB:which_local_host_info(Domain) of
        {ok, #{addr := Addr}} ->
            #{family => Domain,
              addr   => Addr};
        {error, Reason} ->
            ?FAIL(Reason)
    end.



which_local_addr(local = _Domain) ->
    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_addr(Domain) ->
    ?LIB:which_local_addr(Domain).



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

%% 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_support_ip_multicast() ->
    case os:type() of
        {unix, OsName} when (OsName =:= linux) orelse
                            (OsName =:= sunos) ->
            case ?LIB:which_local_host_info(inet) of
                {ok, #{flags := Flags}} ->
                    case lists:member(multicast, Flags) of
                        true ->
                            ok;
                        false ->
                            not_supported(multicast)
                    end;
                {error, Reason} ->
                    not_supported({multicast, Reason})
            end;
        {unix, OsName} ->
            skip(?F("Not Supported: platform ~w", [OsName]));
        Type ->
            skip(?F("Not Supported: platform ~p", [Type]))
    end.

has_support_sock_acceptconn() ->
    has_support_socket_option_sock(acceptconn).

has_support_sock_bindtodevice() ->
    has_support_socket_option_sock(bindtodevice).

has_support_sock_broadcast() ->
    has_support_socket_option_sock(broadcast),
    case ?LIB:which_local_host_info(inet) of
        {ok, #{flags := Flags}} ->
            case lists:member(broadcast, Flags) of
                true ->
                    ok;
                false ->
                    not_supported({broadcast, Flags})
            end;
        {error, Reason} ->
            not_supported({broadcast, Reason})
    end.

has_support_sock_debug() ->
    has_support_socket_option_sock(debug).

has_support_sock_domain() ->
    has_support_socket_option_sock(domain).

has_support_sock_dontroute() ->
    has_support_socket_option_sock(dontroute).

has_support_sock_keepalive() ->
    has_support_socket_option_sock(keepalive).


has_support_ip_add_membership() ->
    has_support_socket_option_ip(add_membership).

has_support_ip_drop_membership() ->
    has_support_socket_option_ip(drop_membership).


has_support_socket_option_ip(Opt) ->
    has_support_socket_option(ip, Opt).

has_support_socket_option_sock(Opt) ->
    has_support_socket_option(socket, Opt).

has_support_socket_option(Level, Option) ->
    case socket:supports(options, Level, Option) of
        true ->
            ok;
        false ->
            skip(?F("Not Supported: ~w option ~w", [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() ->
    ?LIB:has_support_ipv6().



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

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, []).