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 }