lab.nexedi.com/kirr/go123@v0.0.0-20240207185015-8299741fa871/xnet/lonet/lonet_test.go (about)

     1  // Copyright (C) 2018-2021  Nexedi SA and Contributors.
     2  //                          Kirill Smelkov <kirr@nexedi.com>
     3  //
     4  // This program is free software: you can Use, Study, Modify and Redistribute
     5  // it under the terms of the GNU General Public License version 3, or (at your
     6  // option) any later version, as published by the Free Software Foundation.
     7  //
     8  // You can also Link and Combine this program with other software covered by
     9  // the terms of any of the Free Software licenses or any of the Open Source
    10  // Initiative approved licenses and Convey the resulting work. Corresponding
    11  // source of such a combination shall include the source code for all other
    12  // software used.
    13  //
    14  // This program is distributed WITHOUT ANY WARRANTY; without even the implied
    15  // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    16  //
    17  // See COPYING file for full licensing terms.
    18  // See https://www.nexedi.com/licensing for rationale and options.
    19  
    20  package lonet
    21  
    22  import (
    23  	"context"
    24  	"io/ioutil"
    25  	"log"
    26  	"os"
    27  	"os/exec"
    28  	"strings"
    29  	"testing"
    30  
    31  	"golang.org/x/sync/errgroup"
    32  
    33  	"lab.nexedi.com/kirr/go123/exc"
    34  	"lab.nexedi.com/kirr/go123/internal/xtesting"
    35  	"lab.nexedi.com/kirr/go123/xerr"
    36  	"lab.nexedi.com/kirr/go123/xnet/internal/virtnettest"
    37  	"lab.nexedi.com/kirr/go123/xnet/virtnet"
    38  )
    39  
    40  func TestLonetGoGo(t *testing.T) {
    41  	subnet, err := Join(context.Background(), "")
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  
    46  	// XXX TestBasic shutdows subnet, but /tmp/lonet/<name> is left alive.
    47  	virtnettest.TestBasic(t, subnet)
    48  }
    49  
    50  func TestLonetPyPy(t *testing.T) {
    51  	needPy(t)
    52  	err := pytest("-k", "test_lonet_py_basic", "lonet_test.py")
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  }
    57  
    58  func TestLonetGoPy(t *testing.T) {
    59  	needPy(t)
    60  	assert := xtesting.Assert(t)
    61  
    62  	subnet, err := Join(bg, ""); X(err)
    63  	defer func() {
    64  		err := subnet.Close(); X(err)
    65  	}()
    66  
    67  	xaddr := func(addr string) *virtnet.Addr {
    68  		a, err := virtnet.ParseAddr(subnet.Network(), addr); X(err)
    69  		return a
    70  	}
    71  
    72  	hα, err := subnet.NewHost(bg, "α"); X(err)
    73  	lα, err := hα.Listen(bg, ":1"); X(err)
    74  
    75  	wg := &errgroup.Group{}
    76  	wg.Go(exc.Funcx(func() {
    77  		c1, err := lα.Accept(bg); X(err)
    78  		assert.Eq(c1.LocalAddr(), xaddr("α:2"))
    79  		assert.Eq(c1.RemoteAddr(), xaddr("β:2"))
    80  
    81  		_, err = c1.Write([]byte("hello py")); X(err)
    82  		buf := make([]byte, 1024)
    83  		n, err := c1.Read(buf); X(err)
    84  		buf = buf[:n]
    85  		if want := "hello go"; string(buf) != want {
    86  			exc.Raisef("go<-py: got %q; want %q", buf, want)
    87  		}
    88  
    89  		err = c1.Close(); X(err)
    90  
    91  		c2, err := hα.Dial(bg, "β:1"); X(err)
    92  		assert.Eq(c2.LocalAddr(), xaddr("α:2"))
    93  		assert.Eq(c2.RemoteAddr(), xaddr("β:2"))
    94  
    95  		buf = make([]byte, 1024)
    96  		n, err = c2.Read(buf); X(err)
    97  		buf = buf[:n]
    98  		if want := "hello2 go"; string(buf) != want {
    99  			exc.Raisef("go<-py 2: got %q; want %q", buf, want)
   100  		}
   101  		_, err = c2.Write([]byte("hello2 py")); X(err)
   102  
   103  		err = c2.Close(); X(err)
   104  	}))
   105  
   106  
   107  	lonetwork := strings.TrimPrefix(subnet.Network(), "lonet")
   108  	err = pytest("-k", "test_lonet_py_go", "--network", lonetwork, "lonet_test.py")
   109  	X(err)
   110  
   111  	err = wg.Wait(); X(err)
   112  }
   113  
   114  
   115  
   116  var havePy = false
   117  var workRoot string
   118  
   119  // needPy skips test if python is not available
   120  func needPy(t *testing.T) {
   121  	if havePy {
   122  		return
   123  	}
   124  	t.Skipf("skipping: python/pygolang/pytest are not available")
   125  }
   126  
   127  func TestMain(m *testing.M) {
   128  	// check whether we have python + infrastructure for tests
   129  	cmd := exec.Command("python", "-c", "import golang, pytest")
   130  	err := cmd.Run()
   131  	if err == nil {
   132  		havePy = true
   133  	}
   134  
   135  	// setup workroot for all tests
   136  	workRoot, err = ioutil.TempDir("", "t-lonet")
   137  	if err != nil {
   138  		log.Fatal(err)
   139  	}
   140  
   141  	exit := m.Run()
   142  	os.RemoveAll(workRoot)
   143  	os.Exit(exit)
   144  }
   145  
   146  // xworkdir creates temp directory inside workRoot.
   147  func xworkdir(t testing.TB) string {
   148  	work, err := ioutil.TempDir(workRoot, "")
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  	return work
   153  }
   154  
   155  // pytest runs py.test with argv arguments.
   156  func pytest(argv ...string) (err error) {
   157  	defer xerr.Contextf(&err, "pytest %s", argv)
   158  
   159  	cmd := exec.Command("python", "-m", "pytest",
   160  		// ex. with `--registry-dbpath /tmp/1.db` and existing /tmp/1.db,
   161  		// pytest tries to set cachedir=/ , fails and prints warning.
   162  		// Just disable the cache.
   163  		"-p", "no:cacheprovider")
   164  	if testing.Verbose() {
   165  		cmd.Args = append(cmd.Args, "-v", "-s", "--log-file=/dev/stderr")
   166  	} else {
   167  		cmd.Args = append(cmd.Args, "-q", "-q")
   168  	}
   169  	cmd.Args = append(cmd.Args, argv...)
   170  	cmd.Stdout = os.Stdout
   171  	cmd.Stderr = os.Stderr
   172  	return cmd.Run()
   173  }