github.com/ergo-services/ergo@v1.999.224/tests/node_test.go (about)

     1  package tests
     2  
     3  import (
     4  	"context"
     5  	"crypto/md5"
     6  	"crypto/tls"
     7  	"fmt"
     8  	"math/rand"
     9  	"net"
    10  	"reflect"
    11  	"sync"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/ergo-services/ergo"
    16  	"github.com/ergo-services/ergo/etf"
    17  	"github.com/ergo-services/ergo/gen"
    18  	"github.com/ergo-services/ergo/lib"
    19  	"github.com/ergo-services/ergo/node"
    20  	"github.com/ergo-services/ergo/proto/dist"
    21  )
    22  
    23  type benchCase struct {
    24  	name  string
    25  	value etf.Term
    26  }
    27  
    28  func TestNode(t *testing.T) {
    29  	ctx := context.Background()
    30  	listener := node.Listener{
    31  		Listen: 25001,
    32  	}
    33  	opts := node.Options{
    34  		Listeners: []node.Listener{listener},
    35  		Registrar: dist.CreateRegistrarWithLocalEPMD("", 24999),
    36  	}
    37  
    38  	node1, _ := ergo.StartNodeWithContext(ctx, "node123@localhost", "cookies", opts)
    39  	optsTaken := node.Options{
    40  		Registrar: dist.CreateRegistrarWithLocalEPMD("", 24999),
    41  	}
    42  	if _, err := ergo.StartNodeWithContext(ctx, "node123@localhost", "cookies", optsTaken); err == nil {
    43  		t.Fatal("must be failed here")
    44  	}
    45  
    46  	if conn, err := net.Dial("tcp", ":25001"); err != nil {
    47  		fmt.Println("Connect to the node' listening port FAILED")
    48  		t.Fatal(err)
    49  	} else {
    50  		defer conn.Close()
    51  	}
    52  
    53  	if conn, err := net.Dial("tcp", ":24999"); err != nil {
    54  		fmt.Println("Connect to the node' listening EPMD port FAILED")
    55  		t.Fatal(err)
    56  	} else {
    57  		defer conn.Close()
    58  	}
    59  
    60  	gs1 := &testServer{
    61  		res: make(chan interface{}, 2),
    62  	}
    63  	p, e := node1.Spawn("", gen.ProcessOptions{}, gs1)
    64  	if e != nil {
    65  		t.Fatal(e)
    66  	}
    67  
    68  	if !p.IsAlive() {
    69  		t.Fatal("IsAlive: expect 'true', but got 'false'")
    70  	}
    71  
    72  	_, ee := node1.ProcessInfo(p.Self())
    73  	if ee != nil {
    74  		t.Fatal(ee)
    75  	}
    76  
    77  	node1.Stop()
    78  }
    79  
    80  type testFragmentationGS struct {
    81  	gen.Server
    82  }
    83  
    84  func (f *testFragmentationGS) HandleCall(process *gen.ServerProcess, from gen.ServerFrom, message etf.Term) (etf.Term, gen.ServerStatus) {
    85  	md5original := message.(etf.Tuple)[0].(string)
    86  	blob := message.(etf.Tuple)[1].([]byte)
    87  
    88  	result := etf.Atom("ok")
    89  	md5 := fmt.Sprint(md5.Sum(blob))
    90  	if !reflect.DeepEqual(md5original, md5) {
    91  		result = etf.Atom("mismatch")
    92  	}
    93  
    94  	return result, gen.ServerStatusOK
    95  }
    96  
    97  type makeCall struct {
    98  	to      interface{}
    99  	message interface{}
   100  }
   101  type makeCast struct {
   102  	to      interface{}
   103  	message interface{}
   104  }
   105  
   106  type asyncDirect struct {
   107  	ref etf.Ref
   108  	val etf.Term
   109  }
   110  
   111  type syncDirect struct {
   112  	val etf.Term
   113  }
   114  
   115  func (f *testFragmentationGS) HandleDirect(process *gen.ServerProcess, ref etf.Ref, message interface{}) (interface{}, gen.DirectStatus) {
   116  	switch m := message.(type) {
   117  	case makeCall:
   118  		return process.Call(m.to, m.message)
   119  	}
   120  	return nil, lib.ErrUnsupportedRequest
   121  }
   122  
   123  func TestNodeFragmentation(t *testing.T) {
   124  	var wg sync.WaitGroup
   125  
   126  	blob := make([]byte, 1024*1024)
   127  	rand.Read(blob)
   128  	md5 := fmt.Sprint(md5.Sum(blob))
   129  	message := etf.Tuple{md5, blob}
   130  
   131  	node1, _ := ergo.StartNode("nodeT1Fragmentation@localhost", "secret", node.Options{})
   132  	node2, _ := ergo.StartNode("nodeT2Fragmentation@localhost", "secret", node.Options{})
   133  
   134  	tgs := &testFragmentationGS{}
   135  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, tgs)
   136  	p2, e2 := node2.Spawn("", gen.ProcessOptions{}, tgs)
   137  
   138  	if e1 != nil {
   139  		t.Fatal(e1)
   140  	}
   141  	if e2 != nil {
   142  		t.Fatal(e2)
   143  	}
   144  
   145  	// check single call
   146  	call := makeCall{
   147  		to:      p2.Self(),
   148  		message: message,
   149  	}
   150  	check, e := p1.Direct(call)
   151  	if e != nil {
   152  		t.Fatal(e)
   153  	}
   154  	if check != etf.Atom("ok") {
   155  		t.Fatal("md5sum mismatch")
   156  	}
   157  
   158  	for i := 0; i < 10; i++ {
   159  		wg.Add(1)
   160  		go func() {
   161  			p1, _ := node1.Spawn("", gen.ProcessOptions{}, tgs)
   162  			p2, _ := node2.Spawn("", gen.ProcessOptions{}, tgs)
   163  			defer wg.Done()
   164  			for k := 0; k < 100; k++ {
   165  				call := makeCall{
   166  					to:      p2.Self(),
   167  					message: message,
   168  				}
   169  				check, e := p1.Direct(call)
   170  				if e != nil {
   171  					panic("err on call")
   172  				}
   173  				if check != etf.Atom("ok") {
   174  					panic("md5sum mismatch")
   175  				}
   176  			}
   177  
   178  		}()
   179  	}
   180  	wg.Wait()
   181  }
   182  
   183  func TestNodeStaticRoute(t *testing.T) {
   184  	nodeName1 := "nodeT1StaticRoute@localhost"
   185  	nodeName2 := "nodeT2StaticRoute@localhost"
   186  	nodeStaticPort := uint16(9876)
   187  
   188  	node1, e1 := ergo.StartNode(nodeName1, "secret", node.Options{})
   189  	if e1 != nil {
   190  		t.Fatal(e1)
   191  	}
   192  	defer node1.Stop()
   193  
   194  	node2, e2 := ergo.StartNode(nodeName2, "secret", node.Options{})
   195  	if e2 != nil {
   196  		t.Fatal(e2)
   197  	}
   198  	defer node2.Stop()
   199  
   200  	nr, err := node1.Resolve(nodeName2)
   201  	if err != nil {
   202  		t.Fatal("Can't resolve port number for ", nodeName2, err)
   203  	}
   204  
   205  	// override route for nodeName2 with static port
   206  	e := node1.AddStaticRoutePort(nodeName2, nodeStaticPort, node.RouteOptions{})
   207  	if e != nil {
   208  		t.Fatal(e)
   209  	}
   210  	// should be overrided by the new value of nodeStaticPort
   211  	if r, err := node1.Resolve(nodeName2); err != nil || r.Port != nodeStaticPort {
   212  		t.Fatal("Wrong port number after adding static route. Got", r.Port, "Expected", nodeStaticPort)
   213  	}
   214  
   215  	node1.RemoveStaticRoute(nodeName2)
   216  
   217  	// should be resolved into the original port number
   218  	if nr2, err := node1.Resolve(nodeName2); err != nil || nr.Port != nr2.Port {
   219  		t.Fatal("Wrong port number after removing static route")
   220  	}
   221  }
   222  
   223  type handshakeGenServer struct {
   224  	gen.Server
   225  }
   226  
   227  func (h *handshakeGenServer) Init(process *gen.ServerProcess, args ...etf.Term) error {
   228  	return nil
   229  }
   230  
   231  func (h *handshakeGenServer) HandleCall(process *gen.ServerProcess, from gen.ServerFrom, message etf.Term) (etf.Term, gen.ServerStatus) {
   232  	return "pass", gen.ServerStatusOK
   233  }
   234  func (h *handshakeGenServer) HandleDirect(process *gen.ServerProcess, ref etf.Ref, message interface{}) (interface{}, gen.DirectStatus) {
   235  	switch m := message.(type) {
   236  	case makeCall:
   237  		return process.Call(m.to, m.message)
   238  	}
   239  	return nil, lib.ErrUnsupportedRequest
   240  }
   241  
   242  func TestNodeDistHandshake(t *testing.T) {
   243  	fmt.Printf("\n=== Test Node Handshake versions\n")
   244  
   245  	cert, err := lib.GenerateSelfSignedCert("localhost")
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  
   250  	// handshake version 5
   251  	handshake5options := dist.HandshakeOptions{
   252  		Version: dist.HandshakeVersion5,
   253  	}
   254  
   255  	// handshake version 6
   256  	handshake6options := dist.HandshakeOptions{
   257  		Version: dist.HandshakeVersion6,
   258  	}
   259  
   260  	hgs := &handshakeGenServer{}
   261  
   262  	type Pair struct {
   263  		name  string
   264  		nodeA node.Node
   265  		nodeB node.Node
   266  	}
   267  	node1Options5 := node.Options{
   268  		Handshake: dist.CreateHandshake(handshake5options),
   269  	}
   270  	node1, e1 := ergo.StartNode("node1Handshake5@localhost", "secret", node1Options5)
   271  	if e1 != nil {
   272  		t.Fatal(e1)
   273  	}
   274  	node2Options5 := node.Options{
   275  		Handshake: dist.CreateHandshake(handshake5options),
   276  	}
   277  	node2, e2 := ergo.StartNode("node2Handshake5@localhost", "secret", node2Options5)
   278  	if e2 != nil {
   279  		t.Fatal(e2)
   280  	}
   281  	node3Options5 := node.Options{
   282  		Handshake: dist.CreateHandshake(handshake5options),
   283  	}
   284  	node3, e3 := ergo.StartNode("node3Handshake5@localhost", "secret", node3Options5)
   285  	if e3 != nil {
   286  		t.Fatal(e3)
   287  	}
   288  	node4Options6 := node.Options{
   289  		Handshake: dist.CreateHandshake(handshake6options),
   290  	}
   291  	node4, e4 := ergo.StartNode("node4Handshake6@localhost", "secret", node4Options6)
   292  	if e4 != nil {
   293  		t.Fatal(e4)
   294  	}
   295  	// node5, _ := ergo.StartNode("node5Handshake6@localhost", "secret", nodeOptions6)
   296  	// node6, _ := ergo.StartNode("node6Handshake5@localhost", "secret", nodeOptions5)
   297  	node7Options6 := node.Options{
   298  		Handshake: dist.CreateHandshake(handshake6options),
   299  	}
   300  	node7, e7 := ergo.StartNode("node7Handshake6@localhost", "secret", node7Options6)
   301  	if e7 != nil {
   302  		t.Fatal(e7)
   303  	}
   304  	node8Options6 := node.Options{
   305  		Handshake: dist.CreateHandshake(handshake6options),
   306  	}
   307  	node8, e8 := ergo.StartNode("node8Handshake6@localhost", "secret", node8Options6)
   308  	if e8 != nil {
   309  		t.Fatal(e8)
   310  	}
   311  	node9Options5WithTLS := node.Options{
   312  		Handshake: dist.CreateHandshake(handshake5options),
   313  		TLS:       &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true},
   314  	}
   315  	node9, e9 := ergo.StartNode("node9Handshake5@localhost", "secret", node9Options5WithTLS)
   316  	if e9 != nil {
   317  		t.Fatal(e9)
   318  	}
   319  	node10Options5WithTLS := node.Options{
   320  		Handshake: dist.CreateHandshake(handshake5options),
   321  		TLS:       &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true},
   322  	}
   323  	node10, e10 := ergo.StartNode("node10Handshake5@localhost", "secret", node10Options5WithTLS)
   324  	if e10 != nil {
   325  		t.Fatal(e10)
   326  	}
   327  	node11Options5WithTLS := node.Options{
   328  		Handshake: dist.CreateHandshake(handshake5options),
   329  		TLS:       &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true},
   330  	}
   331  	node11, e11 := ergo.StartNode("node11Handshake5@localhost", "secret", node11Options5WithTLS)
   332  	if e11 != nil {
   333  		t.Fatal(e11)
   334  	}
   335  	node12Options6WithTLS := node.Options{
   336  		Handshake: dist.CreateHandshake(handshake6options),
   337  		TLS:       &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true},
   338  	}
   339  	node12, e12 := ergo.StartNode("node12Handshake6@localhost", "secret", node12Options6WithTLS)
   340  	if e12 != nil {
   341  		t.Fatal(e12)
   342  	}
   343  	// node13, _ := ergo.StartNode("node13Handshake6@localhost", "secret", nodeOptions6WithTLS)
   344  	// node14, _ := ergo.StartNode("node14Handshake5@localhost", "secret", nodeOptions5WithTLS)
   345  	node15Options6WithTLS := node.Options{
   346  		Handshake: dist.CreateHandshake(handshake6options),
   347  		TLS:       &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true},
   348  	}
   349  	node15, e15 := ergo.StartNode("node15Handshake6@localhost", "secret", node15Options6WithTLS)
   350  	if e15 != nil {
   351  		t.Fatal(e15)
   352  	}
   353  	node16Options6WithTLS := node.Options{
   354  		Handshake: dist.CreateHandshake(handshake6options),
   355  		TLS:       &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true},
   356  	}
   357  	node16, e16 := ergo.StartNode("node16Handshake6@localhost", "secret", node16Options6WithTLS)
   358  	if e16 != nil {
   359  		t.Fatal(e16)
   360  	}
   361  
   362  	nodes := []Pair{
   363  		{"No TLS. version 5 -> version 5", node1, node2},
   364  		{"No TLS. version 5 -> version 6", node3, node4},
   365  		//Pair{ "No TLS. version 6 -> version 5", node5, node6 },
   366  		{"No TLS. version 6 -> version 6", node7, node8},
   367  		{"With TLS. version 5 -> version 5", node9, node10},
   368  		{"With TLS. version 5 -> version 6", node11, node12},
   369  		//Pair{ "With TLS. version 6 -> version 5", node13, node14 },
   370  		{"With TLS. version 6 -> version 6", node15, node16},
   371  	}
   372  
   373  	defer func(nodes []Pair) {
   374  		for i := range nodes {
   375  			nodes[i].nodeA.Stop()
   376  			nodes[i].nodeB.Stop()
   377  		}
   378  	}(nodes)
   379  
   380  	var pA, pB gen.Process
   381  	var e error
   382  	var result etf.Term
   383  	for i := range nodes {
   384  		pair := nodes[i]
   385  		fmt.Printf("    %s %s -> %s: ", pair.name, pair.nodeA.Name(), pair.nodeB.Name())
   386  		pA, e = pair.nodeA.Spawn("", gen.ProcessOptions{}, hgs)
   387  		if e != nil {
   388  			t.Fatal(e)
   389  		}
   390  		pB, e = pair.nodeB.Spawn("", gen.ProcessOptions{}, hgs)
   391  		if e != nil {
   392  			t.Fatal(e)
   393  		}
   394  
   395  		call := makeCall{
   396  			to:      pB.Self(),
   397  			message: "test",
   398  		}
   399  		result, e = pA.Direct(call)
   400  		if e != nil {
   401  			t.Fatal(e)
   402  		}
   403  		if r, ok := result.(string); !ok || r != "pass" {
   404  			t.Fatal("wrong result")
   405  		}
   406  		fmt.Println("OK")
   407  	}
   408  }
   409  
   410  func TestNodeRemoteSpawn(t *testing.T) {
   411  	fmt.Printf("\n=== Test Node Remote Spawn\n")
   412  	node1opts := node.Options{}
   413  	node1opts.Proxy.Flags = node.DefaultProxyFlags()
   414  	node1opts.Proxy.Flags.EnableRemoteSpawn = false
   415  
   416  	node1, _ := ergo.StartNode("node1remoteSpawn@localhost", "secret", node1opts)
   417  	node2opts := node.Options{}
   418  	node2opts.Proxy.Transit = true
   419  	node2, _ := ergo.StartNode("node2remoteSpawn@localhost", "secret", node2opts)
   420  	node3opts := node.Options{}
   421  	node3opts.Proxy.Accept = true
   422  	node3, _ := ergo.StartNode("node3remoteSpawn@localhost", "secret", node3opts)
   423  	route := node.ProxyRoute{
   424  		Name:  node3.Name(),
   425  		Proxy: node2.Name(),
   426  	}
   427  	node1.AddProxyRoute(route)
   428  	defer node1.Stop()
   429  	defer node2.Stop()
   430  	defer node3.Stop()
   431  
   432  	if err := node1.Connect(node3.Name()); err != nil {
   433  		t.Fatal(err)
   434  	}
   435  
   436  	node2.ProvideRemoteSpawn("remote", &handshakeGenServer{})
   437  	process, err := node1.Spawn("gs1", gen.ProcessOptions{}, &handshakeGenServer{})
   438  	if err != nil {
   439  		t.Fatal(err)
   440  	}
   441  
   442  	opts := gen.RemoteSpawnOptions{
   443  		Name: "remote",
   444  	}
   445  	fmt.Printf("    process gs1@node1 request to spawn new process on node2 and register this process with name 'remote': ")
   446  	gotPid, err := process.RemoteSpawn(node2.Name(), "remote", opts, 1, 2, 3)
   447  	if err != nil {
   448  		t.Fatal(err)
   449  	}
   450  	p := node2.ProcessByName("remote")
   451  	if p == nil {
   452  		t.Fatal("can't find process 'remote' on node2")
   453  	}
   454  	if gotPid != p.Self() {
   455  		t.Fatal("process pid mismatch")
   456  	}
   457  	fmt.Println("OK")
   458  
   459  	fmt.Printf("    process gs1@node1 request to spawn new process on node2 with the same name (must be failed): ")
   460  	_, err = process.RemoteSpawn(node2.Name(), "remote", opts, 1, 2, 3)
   461  	if err != lib.ErrTaken {
   462  		t.Fatal(err)
   463  	}
   464  	fmt.Println("OK")
   465  	fmt.Printf("    process gs1@node1 request to spawn new process on node2 with unregistered behavior name (must be failed): ")
   466  	_, err = process.RemoteSpawn(node2.Name(), "randomname", opts, 1, 2, 3)
   467  	if err != lib.ErrBehaviorUnknown {
   468  		t.Fatal(err)
   469  	}
   470  	fmt.Println("OK")
   471  
   472  	fmt.Printf("    process gs1@node1 request to spawn new process on node3 via proxy node2 and register this process with name 'remote': ")
   473  	node3.ProvideRemoteSpawn("remote", &handshakeGenServer{})
   474  	gotPid, err = process.RemoteSpawn(node3.Name(), "remote", opts, 1, 2, 3)
   475  	if err != nil {
   476  		t.Fatal(err)
   477  	}
   478  	p = node3.ProcessByName("remote")
   479  	if p == nil {
   480  		t.Fatal("can't find process 'remote' on node2")
   481  	}
   482  	if gotPid != p.Self() {
   483  		t.Fatal("process pid mismatch")
   484  	}
   485  	fmt.Println("OK")
   486  	fmt.Printf("    process gs3@node3 request to spawn new process on node1 via proxy node2 (node1 ProxyFlags.RemoteSpawn: false): ")
   487  	process3, err := node3.Spawn("gs3", gen.ProcessOptions{}, &handshakeGenServer{})
   488  	if err != nil {
   489  		t.Fatal(err)
   490  	}
   491  	gotPid, err = process3.RemoteSpawn(node1.Name(), "remote", opts, 1, 2, 3)
   492  	if err != lib.ErrPeerUnsupported {
   493  		t.Fatal(err)
   494  	}
   495  	fmt.Println("OK")
   496  }
   497  
   498  func TestNodeResolveExtra(t *testing.T) {
   499  	cert, err := lib.GenerateSelfSignedCert("localhost")
   500  	if err != nil {
   501  		t.Fatal(err)
   502  	}
   503  	fmt.Printf("\n=== Test Node Resolve Extra \n")
   504  	fmt.Printf("... starting node1 with disabled TLS: ")
   505  	opts1 := node.Options{
   506  		TLS: &tls.Config{InsecureSkipVerify: true},
   507  	}
   508  	node1, err := ergo.StartNode("node1resolveExtra@localhost", "secret", opts1)
   509  	if err != nil {
   510  		t.Fatal(err)
   511  	}
   512  	defer node1.Stop()
   513  	fmt.Println("OK")
   514  	opts2 := node.Options{
   515  		TLS: &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true},
   516  	}
   517  	fmt.Printf("... starting node2 with enabled TLS: ")
   518  	node2, err := ergo.StartNode("node2resolveExtra@localhost", "secret", opts2)
   519  	if err != nil {
   520  		t.Fatal(err)
   521  	}
   522  	defer node2.Stop()
   523  	fmt.Println("OK")
   524  
   525  	fmt.Printf("... node1 resolves node2 with enabled TLS: ")
   526  	route1, err := node1.Resolve("node2resolveExtra@localhost")
   527  	if err != nil {
   528  		t.Fatal(err)
   529  	}
   530  	if route1.Options.TLS == nil {
   531  		t.Fatal("expected TLS value")
   532  	}
   533  	fmt.Println("OK")
   534  
   535  	fmt.Printf("... node2 resolves node1 with disabled TLS: ")
   536  	route2, err := node2.Resolve("node1resolveExtra@localhost")
   537  	if err != nil {
   538  		t.Fatal(err)
   539  	}
   540  	if route2.Options.TLS != nil {
   541  		t.Fatal("expected nil value for TLS")
   542  	}
   543  	fmt.Println("OK")
   544  
   545  	fmt.Printf("... node1 connect to node2: ")
   546  	if err := node1.Connect(node2.Name()); err != nil {
   547  		t.Fatal(err)
   548  	}
   549  	if len(node1.Nodes()) != 1 {
   550  		t.Fatal("no peers")
   551  	}
   552  	if node1.Nodes()[0] != node2.Name() {
   553  		t.Fatal("wrong peer")
   554  	}
   555  	fmt.Println("OK")
   556  
   557  	fmt.Printf("... disconnecting nodes: ")
   558  	time.Sleep(300 * time.Millisecond)
   559  	if err := node1.Disconnect(node2.Name()); err != nil {
   560  		t.Fatal(err)
   561  	}
   562  	if len(node1.Nodes()) > 0 {
   563  		t.Fatal("still connected")
   564  	}
   565  	fmt.Println("OK")
   566  
   567  	fmt.Printf("... node2 connect to node1: ")
   568  	if err := node2.Connect(node1.Name()); err != nil {
   569  		t.Fatal(err)
   570  	}
   571  	if len(node2.Nodes()) != 1 {
   572  		t.Fatal("no peers")
   573  	}
   574  	if node2.Nodes()[0] != node1.Name() {
   575  		t.Fatal("wrong peer")
   576  	}
   577  	fmt.Println("OK")
   578  }
   579  
   580  type failoverServer struct {
   581  	gen.Server
   582  	v chan interface{}
   583  }
   584  
   585  func (f *failoverServer) Init(process *gen.ServerProcess, args ...etf.Term) error {
   586  	return nil
   587  }
   588  func (f *failoverServer) HandleInfo(process *gen.ServerProcess, message etf.Term) gen.ServerStatus {
   589  	if _, yes := gen.IsMessageFallback(message); yes {
   590  		f.v <- message
   591  		return gen.ServerStatusOK
   592  	}
   593  	time.Sleep(300 * time.Millisecond)
   594  	return gen.ServerStatusOK
   595  }
   596  func TestNodeProcessFallback(t *testing.T) {
   597  	fmt.Printf("\n=== Test Node Process Fallback\n")
   598  	fmt.Printf("... start node1: ")
   599  	node1, e := ergo.StartNode("node1processfallback@localhost", "secret", node.Options{})
   600  	if e != nil {
   601  		t.Fatal(e)
   602  	}
   603  	defer node1.Stop()
   604  	fmt.Println("OK")
   605  	popts1 := gen.ProcessOptions{
   606  		MailboxSize: 2,
   607  		Fallback: gen.ProcessFallback{
   608  			Name: "fp",
   609  			Tag:  "test_tag",
   610  		},
   611  	}
   612  	gsf := &failoverServer{
   613  		v: make(chan interface{}, 2),
   614  	}
   615  
   616  	fmt.Printf("... start process p1 (with mailbox size = 2 and fallback process = \"fp\"): ")
   617  	p1, err := node1.Spawn("", popts1, &failoverServer{})
   618  	if err != nil {
   619  		t.Fatal(e)
   620  	}
   621  	fmt.Println("OK")
   622  	fmt.Printf("... start failover process p2 (with name = \"fp\"): ")
   623  	_, err = node1.Spawn("fp", gen.ProcessOptions{}, gsf)
   624  	if err != nil {
   625  		t.Fatal(e)
   626  	}
   627  	fmt.Println("OK")
   628  	fmt.Printf("... sending 4 messages to p1 (4th must wrapped into gen.MessageFallback and forwarded to \"fp\" ): ")
   629  	p1.Send(p1.Self(), "m1")
   630  	p1.Send(p1.Self(), "m2")
   631  	p1.Send(p1.Self(), "m3")
   632  	// bellow message must be forwarded
   633  	p1.Send(p1.Self(), "m4")
   634  
   635  	result := gen.MessageFallback{Process: p1.Self(), Tag: "test_tag", Message: "m4"}
   636  	waitForResultWithValue(t, gsf.v, result)
   637  }
   638  
   639  type compressionServer struct {
   640  	gen.Server
   641  }
   642  
   643  func (c *compressionServer) Init(process *gen.ServerProcess, args ...etf.Term) error {
   644  	return nil
   645  }
   646  
   647  func (c *compressionServer) HandleCall(process *gen.ServerProcess, from gen.ServerFrom, message etf.Term) (etf.Term, gen.ServerStatus) {
   648  	blob := message.(etf.Tuple)[1].([]byte)
   649  	md5original := message.(etf.Tuple)[0].(string)
   650  	md5sum := fmt.Sprint(md5.Sum(blob))
   651  	result := etf.Atom("ok")
   652  	if !reflect.DeepEqual(md5original, md5sum) {
   653  		result = etf.Atom("mismatch")
   654  	}
   655  	return result, gen.ServerStatusOK
   656  }
   657  func (c *compressionServer) HandleDirect(process *gen.ServerProcess, ref etf.Ref, message interface{}) (interface{}, gen.DirectStatus) {
   658  	switch m := message.(type) {
   659  	case makeCall:
   660  		return process.Call(m.to, m.message)
   661  	}
   662  	return nil, lib.ErrUnsupportedRequest
   663  }
   664  func TestNodeCompression(t *testing.T) {
   665  	fmt.Printf("\n=== Test Node Compression \n")
   666  	opts1 := node.Options{}
   667  	opts1.Compression.Enable = true
   668  	// need 1 handler to make Atom cache work
   669  	protoOptions := node.DefaultProtoOptions()
   670  	protoOptions.NumHandlers = 1
   671  	opts1.Proto = dist.CreateProto(protoOptions)
   672  	node1, e := ergo.StartNode("node1compression@localhost", "secret", opts1)
   673  	if e != nil {
   674  		t.Fatal(e)
   675  	}
   676  	defer node1.Stop()
   677  	node2, e := ergo.StartNode("node2compression@localhost", "secret", node.Options{})
   678  	if e != nil {
   679  		t.Fatal(e)
   680  	}
   681  	defer node2.Stop()
   682  
   683  	n1p1, err := node1.Spawn("", gen.ProcessOptions{}, &compressionServer{})
   684  	if err != nil {
   685  		t.Fatal(err)
   686  	}
   687  	n2p1, err := node2.Spawn("", gen.ProcessOptions{}, &compressionServer{})
   688  	if err != nil {
   689  		t.Fatal(err)
   690  	}
   691  
   692  	fmt.Printf("... send 1MB compressed. no fragmentation: ")
   693  	// empty data (no fragmentation)
   694  	blob := make([]byte, 1024*1024)
   695  	md5sum := fmt.Sprint(md5.Sum(blob))
   696  	message := etf.Tuple{md5sum, blob}
   697  
   698  	// send 3 times. that is how atom cache is working -
   699  	// atoms are encoding from cache on 2nd or 3rd sending
   700  	call := makeCall{
   701  		to:      n2p1.Self(),
   702  		message: message,
   703  	}
   704  	for i := 0; i < 3; i++ {
   705  		result, e := n1p1.Direct(call)
   706  		if e != nil {
   707  			t.Fatal(e)
   708  		}
   709  		if result != etf.Atom("ok") {
   710  			t.Fatal(result)
   711  		}
   712  	}
   713  	fmt.Println("OK")
   714  
   715  	fmt.Printf("... send 1MB compressed. with fragmentation: ")
   716  	// will be fragmented
   717  	rnd := lib.RandomString(1024 * 1024)
   718  	blob = []byte(rnd) // compression rate for random string around 50%
   719  	//rand.Read(blob[:66000]) // compression rate for 1MB of random data - 0 % (entropy too big)
   720  	md5sum = fmt.Sprint(md5.Sum(blob))
   721  	message = etf.Tuple{md5sum, blob}
   722  
   723  	call = makeCall{
   724  		to:      n2p1.Self(),
   725  		message: message,
   726  	}
   727  	for i := 0; i < 3; i++ {
   728  		result, e := n1p1.Direct(call)
   729  		if e != nil {
   730  			t.Fatal(e)
   731  		}
   732  		if result != etf.Atom("ok") {
   733  			t.Fatal(result)
   734  		}
   735  	}
   736  	fmt.Println("OK")
   737  }
   738  
   739  func TestNodeProxyConnect(t *testing.T) {
   740  	fmt.Printf("\n=== Test Node Proxy\n")
   741  	fmt.Printf("... connect NodeA to NodeC via NodeB: ")
   742  	optsA := node.Options{}
   743  	nodeA, e := ergo.StartNode("nodeAproxy@localhost", "secret", optsA)
   744  	if e != nil {
   745  		t.Fatal(e)
   746  	}
   747  	defer nodeA.Stop()
   748  
   749  	route := node.ProxyRoute{
   750  		Name:  "nodeCproxy@localhost",
   751  		Proxy: "nodeBproxy@localhost",
   752  	}
   753  	nodeA.AddProxyRoute(route)
   754  
   755  	optsB := node.Options{}
   756  	optsB.Proxy.Transit = true
   757  	nodeB, e := ergo.StartNode("nodeBproxy@localhost", "secret", optsB)
   758  	if e != nil {
   759  		t.Fatal(e)
   760  	}
   761  	defer nodeB.Stop()
   762  	optsC := node.Options{}
   763  	optsC.Proxy.Accept = true
   764  	nodeC, e := ergo.StartNode("nodeCproxy@localhost", "secret", optsC)
   765  	if e != nil {
   766  		t.Fatal(e)
   767  	}
   768  	defer nodeC.Stop()
   769  
   770  	if err := nodeA.Connect("nodeCproxy@localhost"); err != nil {
   771  		t.Fatal(err)
   772  	}
   773  
   774  	indirectNodes := nodeA.NodesIndirect()
   775  	if len(indirectNodes) != 1 {
   776  		t.Fatal("wrong result:", indirectNodes)
   777  	}
   778  	if indirectNodes[0] != "nodeCproxy@localhost" {
   779  		t.Fatal("wrong result:", indirectNodes)
   780  	}
   781  	indirectNodes = nodeC.NodesIndirect()
   782  	if len(indirectNodes) != 1 {
   783  		t.Fatal("wrong result:", indirectNodes)
   784  	}
   785  	if indirectNodes[0] != "nodeAproxy@localhost" {
   786  		t.Fatal("wrong result:", indirectNodes)
   787  	}
   788  	if len(nodeB.NodesIndirect()) > 0 {
   789  		t.Fatal("wrong result:", nodeB.NodesIndirect())
   790  	}
   791  	fmt.Println("OK")
   792  
   793  	fmt.Printf("... disconnect NodeC from NodeA: ")
   794  	nodeC.Disconnect("nodeAproxy@localhost")
   795  	if len(nodeC.NodesIndirect()) > 0 {
   796  		t.Fatal("wrong result:", nodeC.NodesIndirect())
   797  	}
   798  
   799  	time.Sleep(100 * time.Millisecond)
   800  	if len(nodeA.NodesIndirect()) > 0 {
   801  		t.Fatal("wrong result:", nodeA.NodesIndirect())
   802  	}
   803  	fmt.Println("OK")
   804  	nodeB.Stop()
   805  	optsB.Proxy.Transit = false
   806  	nodeB, e = ergo.StartNode("nodeBproxy@localhost", "secret", optsB)
   807  	if e != nil {
   808  		t.Fatal(e)
   809  	}
   810  	fmt.Printf("... connect NodeA to NodeC via NodeB(transit proxy disabled): ")
   811  	e = nodeA.Connect("nodeCproxy@localhost")
   812  	if e == nil {
   813  		t.Fatal("must be error here")
   814  	}
   815  	errMessage := "[nodeBproxy@localhost] proxy feature disabled"
   816  	if e.Error() != errMessage {
   817  		t.Fatal(e)
   818  	}
   819  	fmt.Println("OK")
   820  	nodeB.Stop()
   821  	nodeC.Stop()
   822  
   823  	nodeB.Stop()
   824  	optsB.Proxy.Transit = true
   825  	nodeB, e = ergo.StartNode("nodeBproxy@localhost", "secret", optsB)
   826  	if e != nil {
   827  		t.Fatal(e)
   828  	}
   829  
   830  	optsC.Flags = node.DefaultFlags()
   831  	optsC.Flags.EnableProxy = false
   832  	nodeC, e = ergo.StartNode("nodeCproxy@localhost", "secret", optsC)
   833  	if e != nil {
   834  		t.Fatal(e)
   835  	}
   836  	fmt.Printf("... connect NodeA to NodeC (proxy feature support disabled) via NodeB: ")
   837  	e = nodeA.Connect("nodeCproxy@localhost")
   838  	if e == nil {
   839  		t.Fatal("must be error here")
   840  	}
   841  	errMessage = "[nodeBproxy@localhost] peer does not support this feature"
   842  	if e.Error() != errMessage {
   843  		t.Fatal(e)
   844  	}
   845  	fmt.Println("OK")
   846  	nodeC.Stop()
   847  
   848  	optsC = node.Options{}
   849  	optsC.Proxy.Cookie = "123"
   850  	optsC.Proxy.Accept = true
   851  	nodeC, e = ergo.StartNode("nodeCproxy@localhost", "secret", optsC)
   852  	if e != nil {
   853  		t.Fatal(e)
   854  	}
   855  	fmt.Printf("... connect NodeA to NodeC (with wrong cookie) via NodeB: ")
   856  	e = nodeA.Connect("nodeCproxy@localhost")
   857  	if e == nil {
   858  		t.Fatal("must be error here")
   859  	}
   860  	errMessage = "[nodeCproxy@localhost] can't establish proxy connection"
   861  	if e.Error() != errMessage {
   862  		t.Fatal(e)
   863  	}
   864  	fmt.Println("OK")
   865  
   866  	fmt.Printf("... connect NodeA to NodeC (with correct cookie) via NodeB: ")
   867  	if nodeA.RemoveProxyRoute("nodeCproxy@localhost") == false {
   868  		t.Fatal("proxy route not found")
   869  	}
   870  	route = node.ProxyRoute{
   871  		Name:   "nodeCproxy@localhost",
   872  		Proxy:  "nodeBproxy@localhost",
   873  		Cookie: "123",
   874  	}
   875  	nodeA.AddProxyRoute(route)
   876  
   877  	e = nodeA.Connect("nodeCproxy@localhost")
   878  	if e != nil {
   879  		t.Fatal(e)
   880  	}
   881  	fmt.Println("OK")
   882  
   883  	fmt.Printf("... connect NodeA to NodeD (with enabled encryption) via NodeB: ")
   884  	optsD := node.Options{}
   885  	optsD.Proxy.Cookie = "123"
   886  	optsD.Proxy.Accept = true
   887  	optsD.Proxy.Flags = node.DefaultProxyFlags()
   888  	optsD.Proxy.Flags.EnableEncryption = true
   889  	nodeD, e := ergo.StartNode("nodeDproxy@localhost", "secret", optsD)
   890  	if e != nil {
   891  		t.Fatal(e)
   892  	}
   893  	defer nodeD.Stop()
   894  
   895  	route = node.ProxyRoute{
   896  		Name:   "nodeDproxy@localhost",
   897  		Proxy:  "nodeBproxy@localhost",
   898  		Cookie: "123",
   899  	}
   900  	nodeA.AddProxyRoute(route)
   901  	e = nodeA.Connect("nodeDproxy@localhost")
   902  	if e != nil {
   903  		t.Fatal(e)
   904  	}
   905  	fmt.Println("OK")
   906  
   907  	// use gen serv from test_monitor
   908  	gsA := &testMonitor{
   909  		v: make(chan interface{}, 2),
   910  	}
   911  	gsC := &testMonitor{
   912  		v: make(chan interface{}, 2),
   913  	}
   914  	gsD := &testMonitor{
   915  		v: make(chan interface{}, 2),
   916  	}
   917  	fmt.Printf("... start processA on NodeA: ")
   918  	pA, err := nodeA.Spawn("", gen.ProcessOptions{}, gsA)
   919  	if err != nil {
   920  		t.Fatal(err)
   921  	}
   922  	waitForResultWithValue(t, gsA.v, pA.Self())
   923  	fmt.Printf("... start processC on NodeC: ")
   924  	pC, err := nodeC.Spawn("", gen.ProcessOptions{}, gsC)
   925  	if err != nil {
   926  		t.Fatal(err)
   927  	}
   928  	waitForResultWithValue(t, gsC.v, pC.Self())
   929  	fmt.Printf("... start processD on NodeD: ")
   930  	pD, err := nodeD.Spawn("", gen.ProcessOptions{}, gsD)
   931  	if err != nil {
   932  		t.Fatal(err)
   933  	}
   934  	waitForResultWithValue(t, gsD.v, pD.Self())
   935  
   936  	fmt.Printf("... processA send short message to processC: ")
   937  	if e := pA.Send(pC.Self(), "test"); e != nil {
   938  		t.Fatal(e)
   939  	}
   940  	waitForResultWithValue(t, gsC.v, "test")
   941  
   942  	fmt.Printf("... processA send short message to processD (encrypted): ")
   943  	pA.Send(pD.Self(), "test")
   944  	waitForResultWithValue(t, gsD.v, "test")
   945  
   946  	randomString := []byte(lib.RandomString(1024 * 10))
   947  	pA.SetCompression(true)
   948  	fmt.Printf("... processA send 10K message to processC (compressed): ")
   949  	pA.Send(pC.Self(), randomString)
   950  	waitForResultWithValue(t, gsC.v, randomString)
   951  
   952  	fmt.Printf("... processA send 10K message to processD (compressed, encrypted): ")
   953  	pA.Send(pD.Self(), randomString)
   954  	waitForResultWithValue(t, gsD.v, randomString)
   955  
   956  	pA.SetCompression(false)
   957  	randomString = []byte(lib.RandomString(1024 * 100))
   958  	fmt.Printf("... processA send 100K message to processC (fragmented): ")
   959  	pA.Send(pC.Self(), randomString)
   960  	waitForResultWithValue(t, gsC.v, randomString)
   961  
   962  	fmt.Printf("... processA send 100K message to processD (fragmented, encrypted): ")
   963  	pA.Send(pD.Self(), randomString)
   964  	waitForResultWithValue(t, gsD.v, randomString)
   965  
   966  	pA.SetCompression(true)
   967  	randomString = []byte(lib.RandomString(1024 * 1024))
   968  	fmt.Printf("... processA send 1M message to processC (fragmented, compressed): ")
   969  	pA.Send(pC.Self(), randomString)
   970  	waitForResultWithValue(t, gsC.v, randomString)
   971  
   972  	fmt.Printf("... processA send 1M message to processD (fragmented, compressed, encrypted): ")
   973  	pA.Send(pD.Self(), randomString)
   974  	waitForResultWithValue(t, gsD.v, randomString)
   975  }
   976  
   977  func TestNodeIncarnation(t *testing.T) {
   978  	fmt.Printf("\n=== Test Node Incarnation\n")
   979  	fmt.Printf("... start nodes: ")
   980  	optsA := node.Options{}
   981  	nodeA, e := ergo.StartNode("nodeAincarnation@localhost", "secret", optsA)
   982  	if e != nil {
   983  		t.Fatal(e)
   984  	}
   985  	defer nodeA.Stop()
   986  	route := node.ProxyRoute{
   987  		Name:  "nodeCincarnation@localhost",
   988  		Proxy: "nodeBincarnation@localhost",
   989  	}
   990  	nodeA.AddProxyRoute(route)
   991  	// add sleep to get Creation different value for the next node
   992  	optsB := node.Options{}
   993  	optsB.Proxy.Transit = true
   994  	nodeB, e := ergo.StartNode("nodeBincarnation@localhost", "secret", optsB)
   995  	if e != nil {
   996  		t.Fatal(e)
   997  	}
   998  	defer nodeB.Stop()
   999  	optsC := node.Options{
  1000  		Creation: 1234,
  1001  	}
  1002  	optsC.Proxy.Accept = true
  1003  	nodeC, e := ergo.StartNode("nodeCincarnation@localhost", "secret", optsC)
  1004  	if e != nil {
  1005  		t.Fatal(e)
  1006  	}
  1007  	defer nodeC.Stop()
  1008  
  1009  	if err := nodeA.Connect("nodeCincarnation@localhost"); err != nil {
  1010  		t.Fatal(err)
  1011  	}
  1012  
  1013  	indirectNodes := nodeA.NodesIndirect()
  1014  	if len(indirectNodes) != 1 {
  1015  		t.Fatal("wrong result:", indirectNodes)
  1016  	}
  1017  	if indirectNodes[0] != "nodeCincarnation@localhost" {
  1018  		t.Fatal("wrong result:", indirectNodes)
  1019  	}
  1020  	indirectNodes = nodeC.NodesIndirect()
  1021  	if len(indirectNodes) != 1 {
  1022  		t.Fatal("wrong result:", indirectNodes)
  1023  	}
  1024  	if indirectNodes[0] != "nodeAincarnation@localhost" {
  1025  		t.Fatal("wrong result:", indirectNodes)
  1026  	}
  1027  	if len(nodeB.NodesIndirect()) > 0 {
  1028  		t.Fatal("wrong result:", nodeB.NodesIndirect())
  1029  	}
  1030  	fmt.Println("OK")
  1031  
  1032  	// use gen serv from test_monitor
  1033  	gsA := &testMonitor{
  1034  		v: make(chan interface{}, 2),
  1035  	}
  1036  	gsB := &testMonitor{
  1037  		v: make(chan interface{}, 2),
  1038  	}
  1039  	gsC := &testMonitor{
  1040  		v: make(chan interface{}, 2),
  1041  	}
  1042  	fmt.Printf("... start processA on NodeA: ")
  1043  	pA, err := nodeA.Spawn("", gen.ProcessOptions{}, gsA)
  1044  	if err != nil {
  1045  		t.Fatal(err)
  1046  	}
  1047  	waitForResultWithValue(t, gsA.v, pA.Self())
  1048  
  1049  	fmt.Printf("... start processB on NodeB: ")
  1050  	pB, err := nodeB.Spawn("", gen.ProcessOptions{}, gsB)
  1051  	if err != nil {
  1052  		t.Fatal(err)
  1053  	}
  1054  	waitForResultWithValue(t, gsB.v, pB.Self())
  1055  
  1056  	fmt.Printf("... start processC on NodeC: ")
  1057  	pC, err := nodeC.Spawn("", gen.ProcessOptions{}, gsC)
  1058  	if err != nil {
  1059  		t.Fatal(err)
  1060  	}
  1061  	waitForResultWithValue(t, gsC.v, pC.Self())
  1062  
  1063  	pidC := pC.Self()
  1064  
  1065  	fmt.Printf("... processA send a message to processC (via proxy): ")
  1066  	if e := pA.Send(pidC, "test"); e != nil {
  1067  		t.Fatal(e)
  1068  	}
  1069  	waitForResultWithValue(t, gsC.v, "test")
  1070  	fmt.Printf("... processB send short message to processC: ")
  1071  	if e := pB.Send(pidC, "test"); e != nil {
  1072  		t.Fatal(e)
  1073  	}
  1074  	waitForResultWithValue(t, gsC.v, "test")
  1075  	fmt.Printf("... restart nodeC and processC: ")
  1076  	nodeC.Stop()
  1077  	nodeC.Wait()
  1078  
  1079  	optsC.Creation = 12345
  1080  	nodeC, e = ergo.StartNode("nodeCincarnation@localhost", "secret", optsC)
  1081  	if e != nil {
  1082  		t.Fatal(e)
  1083  	}
  1084  
  1085  	if err := nodeA.Connect("nodeCincarnation@localhost"); err != nil {
  1086  		t.Fatal(err)
  1087  	}
  1088  	pC, err = nodeC.Spawn("", gen.ProcessOptions{}, gsC)
  1089  	if err != nil {
  1090  		t.Fatal(err)
  1091  	}
  1092  	waitForResultWithValue(t, gsC.v, pC.Self())
  1093  
  1094  	fmt.Printf("... processA send a message to previous incarnation of processC (via proxy): ")
  1095  	if e := pA.Send(pidC, "test"); e != lib.ErrProcessIncarnation {
  1096  		t.Fatal("must be ErrProcessIncarnation here", e)
  1097  	}
  1098  	fmt.Println("OK")
  1099  	fmt.Printf("... processB send short message to previous incarnation of processC: ")
  1100  	if e := pB.Send(pidC, "test"); e != lib.ErrProcessIncarnation {
  1101  		t.Fatal(e)
  1102  	}
  1103  	fmt.Println("OK")
  1104  
  1105  	indirectNodes = nodeA.NodesIndirect()
  1106  	if len(indirectNodes) != 1 {
  1107  		t.Fatal("wrong result:", indirectNodes)
  1108  	}
  1109  	if indirectNodes[0] != "nodeCincarnation@localhost" {
  1110  		t.Fatal("wrong result:", indirectNodes)
  1111  	}
  1112  	indirectNodes = nodeC.NodesIndirect()
  1113  	if len(indirectNodes) != 1 {
  1114  		t.Fatal("wrong result:", indirectNodes)
  1115  	}
  1116  	if indirectNodes[0] != "nodeAincarnation@localhost" {
  1117  		t.Fatal("wrong result:", indirectNodes)
  1118  	}
  1119  	if len(nodeB.NodesIndirect()) > 0 {
  1120  		t.Fatal("wrong result:", nodeB.NodesIndirect())
  1121  	}
  1122  }
  1123  
  1124  func BenchmarkNodeCompressionDisabled1MBempty(b *testing.B) {
  1125  	node1name := fmt.Sprintf("nodeB1compressionDis_%d@localhost", b.N)
  1126  	node2name := fmt.Sprintf("nodeB2compressionDis_%d@localhost", b.N)
  1127  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1128  	node2, _ := ergo.StartNode(node2name, "bench", node.Options{})
  1129  	defer node1.Stop()
  1130  	defer node2.Stop()
  1131  	if err := node1.Connect(node2.Name()); err != nil {
  1132  		b.Fatal(err)
  1133  	}
  1134  
  1135  	bgs := &benchGS{}
  1136  
  1137  	var empty [1024 * 1024]byte
  1138  	b.SetParallelism(15)
  1139  	b.RunParallel(func(pb *testing.PB) {
  1140  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1141  		if e1 != nil {
  1142  			b.Fatal(e1)
  1143  		}
  1144  		p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1145  		if e2 != nil {
  1146  			b.Fatal(e2)
  1147  		}
  1148  		b.ResetTimer()
  1149  		for pb.Next() {
  1150  			call := makeCall{
  1151  				to:      p2.Self(),
  1152  				message: empty,
  1153  			}
  1154  			_, e := p1.DirectWithTimeout(call, 30)
  1155  			if e != nil {
  1156  				b.Fatal(e)
  1157  			}
  1158  		}
  1159  
  1160  	})
  1161  }
  1162  func BenchmarkNodeCompressionEnabled1MBempty(b *testing.B) {
  1163  	node1name := fmt.Sprintf("nodeB1compressionEn_%d@localhost", b.N)
  1164  	node2name := fmt.Sprintf("nodeB2compressionEn_%d@localhost", b.N)
  1165  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1166  	node2, _ := ergo.StartNode(node2name, "bench", node.Options{})
  1167  	defer node1.Stop()
  1168  	defer node2.Stop()
  1169  	if err := node1.Connect(node2.Name()); err != nil {
  1170  		b.Fatal(err)
  1171  	}
  1172  
  1173  	bgs := &benchGS{}
  1174  
  1175  	var empty [1024 * 1024]byte
  1176  	//b.SetParallelism(15)
  1177  	b.RunParallel(func(pb *testing.PB) {
  1178  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1179  		if e1 != nil {
  1180  			b.Fatal(e1)
  1181  		}
  1182  		p1.SetCompression(true)
  1183  		p1.SetCompressionLevel(5)
  1184  		p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1185  		if e2 != nil {
  1186  			b.Fatal(e2)
  1187  		}
  1188  		b.ResetTimer()
  1189  		for pb.Next() {
  1190  			call := makeCall{
  1191  				to:      p2.Self(),
  1192  				message: empty,
  1193  			}
  1194  			_, e := p1.DirectWithTimeout(call, 30)
  1195  			if e != nil {
  1196  				b.Fatal(e)
  1197  			}
  1198  		}
  1199  
  1200  	})
  1201  }
  1202  
  1203  func BenchmarkNodeCompressionEnabled1MBstring(b *testing.B) {
  1204  	node1name := fmt.Sprintf("nodeB1compressionEnStr_%d@localhost", b.N)
  1205  	node2name := fmt.Sprintf("nodeB2compressionEnStr_%d@localhost", b.N)
  1206  	node1, e := ergo.StartNode(node1name, "bench", node.Options{})
  1207  	if e != nil {
  1208  		b.Fatal(e)
  1209  	}
  1210  	node2, e := ergo.StartNode(node2name, "bench", node.Options{})
  1211  	if e != nil {
  1212  		b.Fatal(e)
  1213  	}
  1214  	defer node1.Stop()
  1215  	defer node2.Stop()
  1216  	if err := node1.Connect(node2.Name()); err != nil {
  1217  		b.Fatal(err)
  1218  	}
  1219  
  1220  	bgs := &benchGS{}
  1221  
  1222  	randomString := []byte(lib.RandomString(1024 * 1024))
  1223  	b.SetParallelism(15)
  1224  	b.RunParallel(func(pb *testing.PB) {
  1225  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1226  		if e1 != nil {
  1227  			b.Fatal(e1)
  1228  		}
  1229  		p1.SetCompression(true)
  1230  		p1.SetCompressionLevel(5)
  1231  		p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1232  		if e2 != nil {
  1233  			b.Fatal(e2)
  1234  		}
  1235  		b.ResetTimer()
  1236  		for pb.Next() {
  1237  			call := makeCall{
  1238  				to:      p2.Self(),
  1239  				message: randomString,
  1240  			}
  1241  			_, e := p1.DirectWithTimeout(call, 30)
  1242  			if e != nil {
  1243  				b.Fatal(e)
  1244  			}
  1245  		}
  1246  
  1247  	})
  1248  }
  1249  
  1250  type benchGS struct {
  1251  	gen.Server
  1252  }
  1253  
  1254  func (b *benchGS) HandleCall(process *gen.ServerProcess, from gen.ServerFrom, message etf.Term) (etf.Term, gen.ServerStatus) {
  1255  	return etf.Atom("ok"), gen.ServerStatusOK
  1256  }
  1257  func (b *benchGS) HandleDirect(process *gen.ServerProcess, ref etf.Ref, message interface{}) (interface{}, gen.DirectStatus) {
  1258  	switch m := message.(type) {
  1259  	case makeCall:
  1260  		return process.CallWithTimeout(m.to, m.message, 30)
  1261  	}
  1262  	return nil, lib.ErrUnsupportedRequest
  1263  }
  1264  
  1265  func BenchmarkNodeSequentialNetwork(b *testing.B) {
  1266  
  1267  	node1name := fmt.Sprintf("nodeB1_%d@localhost", b.N)
  1268  	node2name := fmt.Sprintf("nodeB2_%d@localhost", b.N)
  1269  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1270  	node2, _ := ergo.StartNode(node2name, "bench", node.Options{})
  1271  
  1272  	bgs := &benchGS{}
  1273  
  1274  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1275  	p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1276  
  1277  	if e1 != nil {
  1278  		b.Fatal(e1)
  1279  	}
  1280  	if e2 != nil {
  1281  		b.Fatal(e2)
  1282  	}
  1283  
  1284  	call := makeCall{
  1285  		to:      p2.Self(),
  1286  		message: 1,
  1287  	}
  1288  	if _, e := p1.Direct(call); e != nil {
  1289  		b.Fatal("single ping", e)
  1290  	}
  1291  
  1292  	b.ResetTimer()
  1293  	for _, c := range benchCases() {
  1294  		b.Run(c.name, func(b *testing.B) {
  1295  			for i := 0; i < b.N; i++ {
  1296  				call := makeCall{
  1297  					to:      p2.Self(),
  1298  					message: c.value,
  1299  				}
  1300  				_, e := p1.Direct(call)
  1301  				if e != nil {
  1302  					b.Fatal(e, i)
  1303  				}
  1304  			}
  1305  		})
  1306  	}
  1307  }
  1308  
  1309  func BenchmarkNodeSequentialLocal(b *testing.B) {
  1310  
  1311  	node1name := fmt.Sprintf("nodeB1Local_%d@localhost", b.N)
  1312  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1313  
  1314  	bgs := &benchGS{}
  1315  
  1316  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1317  	p2, e2 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1318  
  1319  	if e1 != nil {
  1320  		b.Fatal(e1)
  1321  	}
  1322  	if e2 != nil {
  1323  		b.Fatal(e2)
  1324  	}
  1325  
  1326  	call := makeCall{
  1327  		to:      p2.Self(),
  1328  		message: 1,
  1329  	}
  1330  	if _, e := p1.Direct(call); e != nil {
  1331  		b.Fatal("single ping", e)
  1332  	}
  1333  
  1334  	b.ResetTimer()
  1335  	for _, c := range benchCases() {
  1336  		b.Run(c.name, func(b *testing.B) {
  1337  			for i := 0; i < b.N; i++ {
  1338  				call := makeCall{
  1339  					to:      p2.Self(),
  1340  					message: c.value,
  1341  				}
  1342  				_, e := p1.Direct(call)
  1343  				if e != nil {
  1344  					b.Fatal(e, i)
  1345  				}
  1346  			}
  1347  		})
  1348  	}
  1349  }
  1350  
  1351  func BenchmarkNodeParallel(b *testing.B) {
  1352  
  1353  	node1name := fmt.Sprintf("nodeB1Parallel_%d@localhost", b.N)
  1354  	node2name := fmt.Sprintf("nodeB2Parallel_%d@localhost", b.N)
  1355  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1356  	node2, _ := ergo.StartNode(node2name, "bench", node.Options{})
  1357  
  1358  	bgs := &benchGS{}
  1359  
  1360  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1361  	if e1 != nil {
  1362  		b.Fatal(e1)
  1363  	}
  1364  	p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1365  	if e2 != nil {
  1366  		b.Fatal(e2)
  1367  	}
  1368  
  1369  	call := makeCall{
  1370  		to:      p2.Self(),
  1371  		message: "hi",
  1372  	}
  1373  	if _, e := p1.Direct(call); e != nil {
  1374  		b.Fatal("single ping", e)
  1375  	}
  1376  
  1377  	b.SetParallelism(15)
  1378  	b.RunParallel(func(pb *testing.PB) {
  1379  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1380  		if e1 != nil {
  1381  			b.Fatal(e1)
  1382  		}
  1383  		p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1384  		if e2 != nil {
  1385  			b.Fatal(e2)
  1386  		}
  1387  		b.ResetTimer()
  1388  		for pb.Next() {
  1389  			call := makeCall{
  1390  				to:      p2.Self(),
  1391  				message: etf.Atom("ping"),
  1392  			}
  1393  			_, e := p1.Direct(call)
  1394  			if e != nil {
  1395  				b.Fatal(e)
  1396  			}
  1397  		}
  1398  
  1399  	})
  1400  }
  1401  
  1402  func BenchmarkNodeParallelSingleNode(b *testing.B) {
  1403  
  1404  	node1name := fmt.Sprintf("nodeB1ParallelLocal_%d@localhost", b.N)
  1405  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1406  
  1407  	bgs := &benchGS{}
  1408  
  1409  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1410  	if e1 != nil {
  1411  		b.Fatal(e1)
  1412  	}
  1413  	p2, e2 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1414  	if e2 != nil {
  1415  		b.Fatal(e2)
  1416  	}
  1417  
  1418  	call := makeCall{
  1419  		to:      p2.Self(),
  1420  		message: "hi",
  1421  	}
  1422  	if _, e := p1.Direct(call); e != nil {
  1423  		b.Fatal("single ping", e)
  1424  	}
  1425  	b.SetParallelism(15)
  1426  	b.RunParallel(func(pb *testing.PB) {
  1427  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1428  		if e1 != nil {
  1429  			b.Fatal(e1)
  1430  		}
  1431  		p2, e2 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1432  		if e2 != nil {
  1433  			b.Fatal(e2)
  1434  		}
  1435  		b.ResetTimer()
  1436  		for pb.Next() {
  1437  			call := makeCall{
  1438  				to:      p2.Self(),
  1439  				message: etf.Atom("ping"),
  1440  			}
  1441  			_, e := p1.Direct(call)
  1442  			if e != nil {
  1443  				b.Fatal(e)
  1444  			}
  1445  		}
  1446  
  1447  	})
  1448  }
  1449  
  1450  func BenchmarkNodeProxy_NodeA_to_NodeC_direct_Message_1K(b *testing.B) {
  1451  	node1name := fmt.Sprintf("nodeB1ProxyDisabled%d@localhost", b.N)
  1452  	node2name := fmt.Sprintf("nodeB2ProxyDisabled%d@localhost", b.N)
  1453  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1454  	node2, _ := ergo.StartNode(node2name, "bench", node.Options{})
  1455  	defer node1.Stop()
  1456  	defer node2.Stop()
  1457  
  1458  	bgs := &benchGS{}
  1459  
  1460  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1461  	if e1 != nil {
  1462  		b.Fatal(e1)
  1463  	}
  1464  	p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1465  	if e2 != nil {
  1466  		b.Fatal(e2)
  1467  	}
  1468  
  1469  	call := makeCall{
  1470  		to:      p2.Self(),
  1471  		message: "hi",
  1472  	}
  1473  	if _, e := p1.Direct(call); e != nil {
  1474  		b.Fatal("single ping", e)
  1475  	}
  1476  
  1477  	randomString := []byte(lib.RandomString(1024))
  1478  	b.SetParallelism(15)
  1479  	b.RunParallel(func(pb *testing.PB) {
  1480  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1481  		if e1 != nil {
  1482  			b.Fatal(e1)
  1483  		}
  1484  		p2, e2 := node2.Spawn("", gen.ProcessOptions{}, bgs)
  1485  		if e2 != nil {
  1486  			b.Fatal(e2)
  1487  		}
  1488  		b.ResetTimer()
  1489  		for pb.Next() {
  1490  			call := makeCall{
  1491  				to:      p2.Self(),
  1492  				message: randomString,
  1493  			}
  1494  			_, e := p1.Direct(call)
  1495  			if e != nil {
  1496  				b.Fatal(e)
  1497  			}
  1498  		}
  1499  
  1500  	})
  1501  }
  1502  func BenchmarkNodeProxy_NodeA_to_NodeC_via_NodeB_Message_1K(b *testing.B) {
  1503  	node1name := fmt.Sprintf("nodeB1ProxyEnabled1K%d@localhost", b.N)
  1504  	node2name := fmt.Sprintf("nodeB2ProxyEnabled1K%d@localhost", b.N)
  1505  	node3name := fmt.Sprintf("nodeB3ProxyEnabled1K%d@localhost", b.N)
  1506  	node1, _ := ergo.StartNode(node1name, "bench", node.Options{})
  1507  	opts2 := node.Options{}
  1508  	opts2.Proxy.Transit = true
  1509  	node2, _ := ergo.StartNode(node2name, "bench", opts2)
  1510  	node3, _ := ergo.StartNode(node3name, "bench", node.Options{})
  1511  	defer node1.Stop()
  1512  	defer node2.Stop()
  1513  	defer node3.Stop()
  1514  	route := node.ProxyRoute{
  1515  		Name:  node3.Name(),
  1516  		Proxy: node2.Name(),
  1517  	}
  1518  	node1.AddProxyRoute(route)
  1519  
  1520  	bgs := &benchGS{}
  1521  
  1522  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1523  	if e1 != nil {
  1524  		b.Fatal(e1)
  1525  	}
  1526  	p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1527  	if e3 != nil {
  1528  		b.Fatal(e3)
  1529  	}
  1530  
  1531  	call := makeCall{
  1532  		to:      p3.Self(),
  1533  		message: "hi",
  1534  	}
  1535  	if _, e := p1.Direct(call); e != nil {
  1536  		b.Fatal("single ping", e)
  1537  	}
  1538  
  1539  	randomString := []byte(lib.RandomString(1024))
  1540  	b.SetParallelism(15)
  1541  	b.RunParallel(func(pb *testing.PB) {
  1542  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1543  		if e1 != nil {
  1544  			b.Fatal(e1)
  1545  		}
  1546  		p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1547  		if e3 != nil {
  1548  			b.Fatal(e3)
  1549  		}
  1550  		b.ResetTimer()
  1551  		for pb.Next() {
  1552  			call := makeCall{
  1553  				to:      p3.Self(),
  1554  				message: randomString,
  1555  			}
  1556  			_, e := p1.Direct(call)
  1557  			if e != nil {
  1558  				b.Fatal(e)
  1559  			}
  1560  		}
  1561  
  1562  	})
  1563  }
  1564  
  1565  func BenchmarkNodeProxy_NodeA_to_NodeC_via_NodeB_Message_1K_Encrypted(b *testing.B) {
  1566  	node1name := fmt.Sprintf("nodeB1ProxyEnabled1K%d@localhost", b.N)
  1567  	node2name := fmt.Sprintf("nodeB2ProxyEnabled1K%d@localhost", b.N)
  1568  	node3name := fmt.Sprintf("nodeB3ProxyEnabled1K%d@localhost", b.N)
  1569  	opts1 := node.Options{}
  1570  	opts1.Proxy.Flags = node.DefaultProxyFlags()
  1571  	opts1.Proxy.Flags.EnableEncryption = true
  1572  	node1, _ := ergo.StartNode(node1name, "bench", opts1)
  1573  	opts2 := node.Options{}
  1574  	opts2.Proxy.Transit = true
  1575  	node2, _ := ergo.StartNode(node2name, "bench", opts2)
  1576  	node3, _ := ergo.StartNode(node3name, "bench", node.Options{})
  1577  	defer node1.Stop()
  1578  	defer node2.Stop()
  1579  	defer node3.Stop()
  1580  	route := node.ProxyRoute{
  1581  		Name:  node3.Name(),
  1582  		Proxy: node2.Name(),
  1583  	}
  1584  	node1.AddProxyRoute(route)
  1585  
  1586  	bgs := &benchGS{}
  1587  
  1588  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1589  	if e1 != nil {
  1590  		b.Fatal(e1)
  1591  	}
  1592  	p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1593  	if e3 != nil {
  1594  		b.Fatal(e3)
  1595  	}
  1596  
  1597  	call := makeCall{
  1598  		to:      p3.Self(),
  1599  		message: "hi",
  1600  	}
  1601  	if _, e := p1.Direct(call); e != nil {
  1602  		b.Fatal("single ping", e)
  1603  	}
  1604  
  1605  	randomString := []byte(lib.RandomString(1024))
  1606  	b.SetParallelism(15)
  1607  	b.RunParallel(func(pb *testing.PB) {
  1608  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1609  		if e1 != nil {
  1610  			b.Fatal(e1)
  1611  		}
  1612  		p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1613  		if e3 != nil {
  1614  			b.Fatal(e3)
  1615  		}
  1616  		b.ResetTimer()
  1617  		for pb.Next() {
  1618  			call := makeCall{
  1619  				to:      p3.Self(),
  1620  				message: randomString,
  1621  			}
  1622  			_, e := p1.Direct(call)
  1623  			if e != nil {
  1624  				b.Fatal(e)
  1625  			}
  1626  		}
  1627  
  1628  	})
  1629  }
  1630  
  1631  func BenchmarkNodeProxy_NodeA_to_NodeC_via_NodeB_Message_1M_Compressed(b *testing.B) {
  1632  	node1name := fmt.Sprintf("nodeB1ProxyEnabled1K%d@localhost", b.N)
  1633  	node2name := fmt.Sprintf("nodeB2ProxyEnabled1K%d@localhost", b.N)
  1634  	node3name := fmt.Sprintf("nodeB3ProxyEnabled1K%d@localhost", b.N)
  1635  	opts1 := node.Options{}
  1636  	opts1.Proxy.Flags = node.DefaultProxyFlags()
  1637  	opts1.Proxy.Flags.EnableEncryption = false
  1638  	node1, _ := ergo.StartNode(node1name, "bench", opts1)
  1639  	opts2 := node.Options{}
  1640  	opts2.Proxy.Transit = true
  1641  	node2, _ := ergo.StartNode(node2name, "bench", opts2)
  1642  	node3, _ := ergo.StartNode(node3name, "bench", node.Options{})
  1643  	defer node1.Stop()
  1644  	defer node2.Stop()
  1645  	defer node3.Stop()
  1646  	route := node.ProxyRoute{
  1647  		Name:  node3.Name(),
  1648  		Proxy: node2.Name(),
  1649  	}
  1650  	node1.AddProxyRoute(route)
  1651  
  1652  	bgs := &benchGS{}
  1653  
  1654  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1655  	if e1 != nil {
  1656  		b.Fatal(e1)
  1657  	}
  1658  	p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1659  	if e3 != nil {
  1660  		b.Fatal(e3)
  1661  	}
  1662  
  1663  	call := makeCall{
  1664  		to:      p3.Self(),
  1665  		message: "hi",
  1666  	}
  1667  	if _, e := p1.Direct(call); e != nil {
  1668  		b.Fatal("single ping", e)
  1669  	}
  1670  
  1671  	randomString := []byte(lib.RandomString(1024 * 1024))
  1672  	b.SetParallelism(15)
  1673  	b.RunParallel(func(pb *testing.PB) {
  1674  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1675  		if e1 != nil {
  1676  			b.Fatal(e1)
  1677  		}
  1678  		p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1679  		if e3 != nil {
  1680  			b.Fatal(e3)
  1681  		}
  1682  		b.ResetTimer()
  1683  		for pb.Next() {
  1684  			call := makeCall{
  1685  				to:      p3.Self(),
  1686  				message: randomString,
  1687  			}
  1688  			_, e := p1.Direct(call)
  1689  			if e != nil {
  1690  				b.Fatal(e)
  1691  			}
  1692  		}
  1693  
  1694  	})
  1695  }
  1696  
  1697  func BenchmarkNodeProxy_NodeA_to_NodeC_via_NodeB_Message_1M_CompressedEncrypted(b *testing.B) {
  1698  	node1name := fmt.Sprintf("nodeB1ProxyEnabled1K%d@localhost", b.N)
  1699  	node2name := fmt.Sprintf("nodeB2ProxyEnabled1K%d@localhost", b.N)
  1700  	node3name := fmt.Sprintf("nodeB3ProxyEnabled1K%d@localhost", b.N)
  1701  	opts1 := node.Options{}
  1702  	opts1.Proxy.Flags = node.DefaultProxyFlags()
  1703  	opts1.Proxy.Flags.EnableEncryption = true
  1704  	node1, _ := ergo.StartNode(node1name, "bench", opts1)
  1705  	opts2 := node.Options{}
  1706  	opts2.Proxy.Transit = true
  1707  	node2, _ := ergo.StartNode(node2name, "bench", opts2)
  1708  	node3, _ := ergo.StartNode(node3name, "bench", node.Options{})
  1709  	defer node1.Stop()
  1710  	defer node2.Stop()
  1711  	defer node3.Stop()
  1712  	route := node.ProxyRoute{
  1713  		Name:  node3.Name(),
  1714  		Proxy: node2.Name(),
  1715  	}
  1716  	node1.AddProxyRoute(route)
  1717  
  1718  	bgs := &benchGS{}
  1719  
  1720  	p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1721  	if e1 != nil {
  1722  		b.Fatal(e1)
  1723  	}
  1724  	p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1725  	if e3 != nil {
  1726  		b.Fatal(e3)
  1727  	}
  1728  
  1729  	call := makeCall{
  1730  		to:      p3.Self(),
  1731  		message: "hi",
  1732  	}
  1733  	if _, e := p1.Direct(call); e != nil {
  1734  		b.Fatal("single ping", e)
  1735  	}
  1736  
  1737  	randomString := []byte(lib.RandomString(1024 * 1024))
  1738  	b.SetParallelism(15)
  1739  	b.RunParallel(func(pb *testing.PB) {
  1740  		p1, e1 := node1.Spawn("", gen.ProcessOptions{}, bgs)
  1741  		if e1 != nil {
  1742  			b.Fatal(e1)
  1743  		}
  1744  		p1.SetCompression(true)
  1745  		p3, e3 := node3.Spawn("", gen.ProcessOptions{}, bgs)
  1746  		if e3 != nil {
  1747  			b.Fatal(e3)
  1748  		}
  1749  		b.ResetTimer()
  1750  		for pb.Next() {
  1751  			call := makeCall{
  1752  				to:      p3.Self(),
  1753  				message: randomString,
  1754  			}
  1755  			_, e := p1.Direct(call)
  1756  			if e != nil {
  1757  				b.Fatal(e)
  1758  			}
  1759  		}
  1760  
  1761  	})
  1762  }
  1763  
  1764  func benchCases() []benchCase {
  1765  	return []benchCase{
  1766  		{"number", 12345},
  1767  		{"string", "hello world"},
  1768  		{"tuple (PID)",
  1769  			etf.Pid{
  1770  				Node:     "node@localhost",
  1771  				ID:       1000,
  1772  				Creation: 1,
  1773  			},
  1774  		},
  1775  		{"binary 1MB", make([]byte, 1024*1024)},
  1776  	}
  1777  }