Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
a01ce812
Commit
a01ce812
authored
May 15, 2018
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
1bbebed5
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
0 additions
and
1368 deletions
+0
-1368
go/xcommon/xnet/lonet/lonet.go
go/xcommon/xnet/lonet/lonet.go
+0
-630
go/xcommon/xnet/lonet/lonet.py
go/xcommon/xnet/lonet/lonet.py
+0
-31
go/xcommon/xnet/lonet/lonet_test.go
go/xcommon/xnet/lonet/lonet_test.go
+0
-172
go/xcommon/xnet/lonet/registry.go
go/xcommon/xnet/lonet/registry.go
+0
-104
go/xcommon/xnet/lonet/registry_sqlite.go
go/xcommon/xnet/lonet/registry_sqlite.go
+0
-283
go/xcommon/xnet/lonet/registry_sqlite_test.go
go/xcommon/xnet/lonet/registry_sqlite_test.go
+0
-148
No files found.
go/xcommon/xnet/lonet/lonet.go
deleted
100644 → 0
View file @
1bbebed5
This diff is collapsed.
Click to expand it.
go/xcommon/xnet/lonet/lonet.py
deleted
100644 → 0
View file @
1bbebed5
# Copyright (C) 2018 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
# TODO doc, code
# XXX see lonet.go for lonet organization and protocol.
class
SQLiteRegistry
(
object
):
def
__init__
(
self
,
dburi
,
network
):
# XXX open
self
.
setup
(
network
)
# TODO
go/xcommon/xnet/lonet/lonet_test.go
deleted
100644 → 0
View file @
1bbebed5
// Copyright (C) 2018 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package
lonet
import
(
"context"
"fmt"
"io"
"net"
"reflect"
"testing"
"golang.org/x/sync/errgroup"
"lab.nexedi.com/kirr/go123/exc"
)
// FIXME dup from pipenet:
// ---- 8< ----
type
mklistener
interface
{
Listen
(
string
)
(
net
.
Listener
,
error
)
}
func
xlisten
(
n
mklistener
,
laddr
string
)
net
.
Listener
{
l
,
err
:=
n
.
Listen
(
laddr
)
exc
.
Raiseif
(
err
)
return
l
}
func
xaccept
(
l
net
.
Listener
)
net
.
Conn
{
c
,
err
:=
l
.
Accept
()
exc
.
Raiseif
(
err
)
return
c
}
type
dialer
interface
{
Dial
(
context
.
Context
,
string
)
(
net
.
Conn
,
error
)
}
func
xdial
(
n
dialer
,
addr
string
)
net
.
Conn
{
c
,
err
:=
n
.
Dial
(
context
.
Background
(),
addr
)
exc
.
Raiseif
(
err
)
return
c
}
func
xread
(
r
io
.
Reader
)
string
{
buf
:=
make
([]
byte
,
4096
)
n
,
err
:=
r
.
Read
(
buf
)
exc
.
Raiseif
(
err
)
return
string
(
buf
[
:
n
])
}
func
xwrite
(
w
io
.
Writer
,
data
string
)
{
_
,
err
:=
w
.
Write
([]
byte
(
data
))
exc
.
Raiseif
(
err
)
}
func
xwait
(
w
interface
{
Wait
()
error
})
{
err
:=
w
.
Wait
()
exc
.
Raiseif
(
err
)
}
func
assertEq
(
t
*
testing
.
T
,
a
,
b
interface
{})
{
t
.
Helper
()
if
!
reflect
.
DeepEqual
(
a
,
b
)
{
fmt
.
Printf
(
"not equal:
\n
have: %v
\n
want: %v
\n
"
,
a
,
b
)
t
.
Errorf
(
"not equal:
\n
have: %v
\n
want: %v"
,
a
,
b
)
exc
.
Raise
(
0
)
}
}
// ---- 8< ----
// TODO test go-go
// TODO test go-py
// XXX handshake:
// - ok,
// - econnrefused (no such host, port not listening)
// - network mismatch
// - invalid request
func
TestLonet
(
t
*
testing
.
T
)
{
// FIXME ~100% dup from TestPipeNet
X
:=
exc
.
Raiseif
ctx
:=
context
.
Background
()
subnet
,
err
:=
Join
(
ctx
,
""
)
X
(
err
)
// XXX defer shutdown/rm this lonet fully?
xaddr
:=
func
(
addr
string
)
*
Addr
{
a
,
err
:=
subnet
.
parseAddr
(
addr
)
X
(
err
)
return
a
}
hα
,
err
:=
subnet
.
NewHost
(
ctx
,
"α"
)
X
(
err
)
hβ
,
err
:=
subnet
.
NewHost
(
ctx
,
"β"
)
X
(
err
)
assertEq
(
t
,
hα
.
Network
(),
subnet
.
Network
())
assertEq
(
t
,
hβ
.
Network
(),
subnet
.
Network
())
assertEq
(
t
,
hα
.
Name
(),
"α"
)
assertEq
(
t
,
hβ
.
Name
(),
"β"
)
l1
,
err
:=
hα
.
Listen
(
""
)
X
(
err
)
assertEq
(
t
,
l1
.
Addr
(),
xaddr
(
"α:1"
))
// zero port always stays unused even after autobind
_
,
err
=
hα
.
Dial
(
ctx
,
":0"
)
assertEq
(
t
,
err
,
&
net
.
OpError
{
Op
:
"dial"
,
Net
:
subnet
.
Network
(),
Addr
:
xaddr
(
"α:0"
),
Err
:
errConnRefused
})
wg
:=
&
errgroup
.
Group
{}
wg
.
Go
(
exc
.
Funcx
(
func
()
{
c1s
:=
xaccept
(
l1
)
assertEq
(
t
,
c1s
.
LocalAddr
(),
xaddr
(
"α:2"
))
assertEq
(
t
,
c1s
.
RemoteAddr
(),
xaddr
(
"β:1"
))
assertEq
(
t
,
xread
(
c1s
),
"ping"
)
xwrite
(
c1s
,
"pong"
)
c2s
:=
xaccept
(
l1
)
assertEq
(
t
,
c2s
.
LocalAddr
(),
xaddr
(
"α:3"
))
assertEq
(
t
,
c2s
.
RemoteAddr
(),
xaddr
(
"β:2"
))
assertEq
(
t
,
xread
(
c2s
),
"hello"
)
xwrite
(
c2s
,
"world"
)
}))
c1c
:=
xdial
(
hβ
,
"α:1"
)
assertEq
(
t
,
c1c
.
LocalAddr
(),
xaddr
(
"β:1"
))
assertEq
(
t
,
c1c
.
RemoteAddr
(),
xaddr
(
"α:2"
))
xwrite
(
c1c
,
"ping"
)
assertEq
(
t
,
xread
(
c1c
),
"pong"
)
c2c
:=
xdial
(
hβ
,
"α:1"
)
assertEq
(
t
,
c2c
.
LocalAddr
(),
xaddr
(
"β:2"
))
assertEq
(
t
,
c2c
.
RemoteAddr
(),
xaddr
(
"α:3"
))
xwrite
(
c2c
,
"hello"
)
assertEq
(
t
,
xread
(
c2c
),
"world"
)
xwait
(
wg
)
l2
:=
xlisten
(
hα
,
":0"
)
// autobind again
assertEq
(
t
,
l2
.
Addr
(),
xaddr
(
"α:4"
))
}
go/xcommon/xnet/lonet/registry.go
deleted
100644 → 0
View file @
1bbebed5
// Copyright (C) 2018 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package
lonet
// registry of network hosts.
import
(
"context"
"errors"
"fmt"
)
// registry represents access to lonet network registry.
//
// The registry holds information about hosts available on the network, and
// for each host its OS listening address. Whenever host α needs to establish XXX dup with lonet.go
// connection to address on host β, it queries the registry for β and further
// talks to β on that address. Correspondingly when a host joins the network,
// it announces itself to the registry so that other hosts could see it.
//
// The registry could be implemented in several ways, for example:
//
// - dedicated network server,
// - hosts broadcasting information to each other similar to ARP,
// - shared memory or file,
// - ...
type
registry
interface
{
// XXX + network name?
// Announce announces host to registry.
//
// The host is named as hostname on lonet network and is listening for
// incoming lonet protocol connections on OS-level osladdr address.
//
// Returned error, if !nil, is *registryError with .Err describing the
// error cause:
//
// - errRegistryDown if registry cannot be accessed, XXX (and its underlying cause?)
// - errHostDup if hostname was already announced,
// - some other error indicating e.g. IO problem.
Announce
(
ctx
context
.
Context
,
hostname
,
osladdr
string
)
error
// Query queries registry for host.
//
// If successful - it returns OS-level network address to connect to
// the host via lonet protocol handshake.
//
// Returned error, if !nil, is *registryError with .Err describing the
// error cause:
//
// - errRegistryDown if registry cannot be accessed, XXX ^^^
// - errNoHost if hostname was not announced to registry,
// - some other error indicating e.g. IO problem.
Query
(
ctx
context
.
Context
,
hostname
string
)
(
osladdr
string
,
_
error
)
// Close closes access to registry.
//
// Close interrupts all in-flight Announce and Query requests started
// via closing registry connection. Those interrupted requests will
// return with errRegistryDown error cause.
Close
()
error
}
var
errRegistryDown
=
errors
.
New
(
"registry is down"
)
var
errNoHost
=
errors
.
New
(
"no such host"
)
var
errHostDup
=
errors
.
New
(
"host already registered"
)
// registryError represents an error of a registry operation.
type
registryError
struct
{
// XXX name of the network? - XXX yes
Registry
string
// name of the registry
Op
string
// operation that failed
Args
interface
{}
// operation arguments, if any
Err
error
// actual error that occurred during the operation
}
func
(
e
*
registryError
)
Error
()
string
{
s
:=
e
.
Registry
+
": "
+
e
.
Op
if
e
.
Args
!=
nil
{
s
+=
fmt
.
Sprintf
(
" %s"
,
e
.
Args
)
}
s
+=
": "
+
e
.
Err
.
Error
()
return
s
}
func
(
e
*
registryError
)
Cause
()
error
{
return
e
.
Err
}
go/xcommon/xnet/lonet/registry_sqlite.go
deleted
100644 → 0
View file @
1bbebed5
// Copyright (C) 2018 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package
lonet
// registry implemented as shared SQLite file.
import
(
"context"
"errors"
"fmt"
"crawshaw.io/sqlite"
"crawshaw.io/sqlite/sqliteutil"
"lab.nexedi.com/kirr/go123/xerr"
)
// registry schema (keep in sync wrt .setup())
//
// hosts:
// hostname text !null PK
// osladdr text !null
//
// meta:
// name text !null PK
// value text !null
//
// "schemaver" text - version of db schema.
// "network" text - name of lonet network this registry serves.
const
schemaVer
=
"lonet.1"
type
sqliteRegistry
struct
{
dbpool
*
sqlite
.
Pool
uri
string
// URI db was originally opened with
}
// openRegistrySQLite opens SQLite registry located at dburi.
//
// the registry is setup/verified to be serving specified lonet network.
func
openRegistrySQLite
(
ctx
context
.
Context
,
dburi
,
network
string
)
(
_
*
sqliteRegistry
,
err
error
)
{
r
:=
&
sqliteRegistry
{
uri
:
dburi
}
defer
r
.
regerr
(
&
err
,
"open"
)
dbpool
,
err
:=
sqlite
.
Open
(
dburi
,
0
,
/* poolSize= */
16
)
// XXX pool size ok?
if
err
!=
nil
{
return
nil
,
err
}
r
.
dbpool
=
dbpool
// initialize/check db
err
=
r
.
setup
(
ctx
,
network
)
if
err
!=
nil
{
r
.
Close
()
return
nil
,
err
}
return
r
,
nil
}
// Close implements registry.
func
(
r
*
sqliteRegistry
)
Close
()
(
err
error
)
{
defer
r
.
regerr
(
&
err
,
"close"
)
return
r
.
dbpool
.
Close
()
}
// withConn runs f on a dbpool connection.
//
// connection is first allocated from dbpool and put back after call to f.
func
(
r
*
sqliteRegistry
)
withConn
(
ctx
context
.
Context
,
f
func
(
*
sqlite
.
Conn
)
error
)
error
{
conn
:=
r
.
dbpool
.
Get
(
ctx
.
Done
())
if
conn
==
nil
{
// either ctx cancel or dbpool close
if
ctx
.
Err
()
!=
nil
{
return
ctx
.
Err
()
}
return
errRegistryDown
// db closed
}
defer
r
.
dbpool
.
Put
(
conn
)
return
f
(
conn
)
}
var
errNoRows
=
errors
.
New
(
"query: empty result"
)
var
errManyRows
=
errors
.
New
(
"query: multiple results"
)
// query1 is like sqliteutil.Exec but checks that exactly 1 row is returned.
//
// if query results in no rows - errNoRows is returned.
// if query results in more than 1 row - errManyRows is returned.
func
query1
(
conn
*
sqlite
.
Conn
,
query
string
,
resultf
func
(
stmt
*
sqlite
.
Stmt
),
argv
...
interface
{})
error
{
nrow
:=
0
err
:=
sqliteutil
.
Exec
(
conn
,
query
,
func
(
stmt
*
sqlite
.
Stmt
)
error
{
if
nrow
==
1
{
return
errManyRows
}
nrow
++
resultf
(
stmt
)
return
nil
},
argv
...
)
if
err
!=
nil
{
return
err
}
if
nrow
==
0
{
return
errNoRows
}
return
nil
}
// setup initializes/checks registry database to be of expected schema and configuration.
func
(
r
*
sqliteRegistry
)
setup
(
ctx
context
.
Context
,
network
string
)
(
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"setup %q"
,
network
)
return
r
.
withConn
(
ctx
,
func
(
conn
*
sqlite
.
Conn
)
(
err
error
)
{
// NOTE: keep in sync wrt top-level text.
err
=
sqliteutil
.
ExecScript
(
conn
,
`
CREATE TABLE IF NOT EXISTS hosts (
hostname TEXT NON NULL PRIMARY KEY,
osladdr TEXT NON NULL
);
CREATE TABLE IF NOT EXISTS meta (
name TEXT NON NULL PRIMARY KEY,
value TEXT NON NULL
);
`
)
if
err
!=
nil
{
return
err
}
// do whole checks/init under transaction, so that there is
// e.g. no race wrt another process setting config.
defer
sqliteutil
.
Save
(
conn
)(
&
err
)
// check/init schema version
ver
,
err
:=
r
.
config
(
conn
,
"schemaver"
)
if
err
!=
nil
{
return
err
}
if
ver
==
""
{
ver
=
schemaVer
err
=
r
.
setConfig
(
conn
,
"schemaver"
,
ver
)
if
err
!=
nil
{
return
err
}
}
if
ver
!=
schemaVer
{
return
fmt
.
Errorf
(
"schema version mismatch: want %q; have %q"
,
schemaVer
,
ver
)
}
// check/init network name
dbnetwork
,
err
:=
r
.
config
(
conn
,
"network"
)
if
err
!=
nil
{
return
err
}
if
dbnetwork
==
""
{
dbnetwork
=
network
err
=
r
.
setConfig
(
conn
,
"network"
,
dbnetwork
)
if
err
!=
nil
{
return
err
}
}
if
dbnetwork
!=
network
{
return
fmt
.
Errorf
(
"network name mismatch: want %q; have %q"
,
network
,
dbnetwork
)
}
return
nil
})
}
// config gets one registry configuration value by name.
//
// if there is no record corresponding to name - ("", nil) is returned.
// XXX add ok ret to indicate presence of value?
func
(
r
*
sqliteRegistry
)
config
(
conn
*
sqlite
.
Conn
,
name
string
)
(
value
string
,
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"config: get %q"
,
name
)
err
=
query1
(
conn
,
"SELECT value FROM meta WHERE name = ?"
,
func
(
stmt
*
sqlite
.
Stmt
)
{
value
=
stmt
.
ColumnText
(
0
)
},
name
)
switch
err
{
case
errNoRows
:
return
""
,
nil
case
errManyRows
:
value
=
""
}
return
value
,
err
}
// setConfig sets one registry configuration value by name.
func
(
r
*
sqliteRegistry
)
setConfig
(
conn
*
sqlite
.
Conn
,
name
,
value
string
)
(
err
error
)
{
defer
xerr
.
Contextf
(
&
err
,
"config: set %q = %q"
,
name
,
value
)
err
=
sqliteutil
.
Exec
(
conn
,
"INSERT OR REPLACE INTO meta (name, value) VALUES (?, ?)"
,
nil
,
name
,
value
)
return
err
}
// Announce implements registry.
func
(
r
*
sqliteRegistry
)
Announce
(
ctx
context
.
Context
,
hostname
,
osladdr
string
)
(
err
error
)
{
defer
r
.
regerr
(
&
err
,
"announce"
,
hostname
,
osladdr
)
return
r
.
withConn
(
ctx
,
func
(
conn
*
sqlite
.
Conn
)
error
{
err
:=
sqliteutil
.
Exec
(
conn
,
"INSERT INTO hosts (hostname, osladdr) VALUES (?, ?)"
,
nil
,
hostname
,
osladdr
)
switch
sqlite
.
ErrCode
(
err
)
{
case
sqlite
.
SQLITE_CONSTRAINT_UNIQUE
:
err
=
errHostDup
}
return
err
})
}
var
errRegDup
=
errors
.
New
(
"registry broken: duplicate host entries"
)
// Query implements registry.
func
(
r
*
sqliteRegistry
)
Query
(
ctx
context
.
Context
,
hostname
string
)
(
osladdr
string
,
err
error
)
{
defer
r
.
regerr
(
&
err
,
"query"
,
hostname
)
err
=
r
.
withConn
(
ctx
,
func
(
conn
*
sqlite
.
Conn
)
error
{
err
:=
query1
(
conn
,
"SELECT osladdr FROM hosts WHERE hostname = ?"
,
func
(
stmt
*
sqlite
.
Stmt
)
{
osladdr
=
stmt
.
ColumnText
(
0
)
},
hostname
)
switch
err
{
case
errNoRows
:
return
errNoHost
case
errManyRows
:
// hostname is PK - we should not get several results
osladdr
=
""
return
errRegDup
}
return
err
})
return
osladdr
,
err
}
// regerr is syntactic sugar to wrap !nil *errp into registryError.
//
// intended too be used like
//
// defer r.regerr(&err, "operation", arg1, arg2, ...)
func
(
r
*
sqliteRegistry
)
regerr
(
errp
*
error
,
op
string
,
args
...
interface
{})
{
if
*
errp
==
nil
{
return
}
// XXX name of the network
*
errp
=
&
registryError
{
Registry
:
r
.
uri
,
Op
:
op
,
Args
:
args
,
Err
:
*
errp
,
}
}
go/xcommon/xnet/lonet/registry_sqlite_test.go
deleted
100644 → 0
View file @
1bbebed5
// Copyright (C) 2018 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package
lonet
import
(
"context"
"fmt"
"io/ioutil"
"os"
"testing"
"lab.nexedi.com/kirr/go123/exc"
)
func
TestRegistrySQLite
(
t
*
testing
.
T
)
{
X
:=
exc
.
Raiseif
work
,
err
:=
ioutil
.
TempDir
(
""
,
"t-registry-sqlite"
)
X
(
err
)
defer
os
.
RemoveAll
(
work
)
dbpath
:=
work
+
"/1.db"
ctx
:=
context
.
Background
()
r
,
err
:=
openRegistrySQLite
(
ctx
,
dbpath
,
"aaa"
)
X
(
err
)
// query checks that result of Query(hostname) is as expected.
//
// if expect is error - it checks that Query returns error with cause == expect.
// otherwise expect must be string and it will check that Query
// succeeds and returns osladdr == expect.
query
:=
func
(
r
*
sqliteRegistry
,
hostname
string
,
expect
interface
{})
{
// XXX ^^^ -> `r registry` (needs .Network() to get network name) ?
t
.
Helper
()
osladdr
,
err
:=
r
.
Query
(
ctx
,
hostname
)
if
ewant
,
iserr
:=
expect
.
(
error
);
iserr
{
// error expected
// XXX construct full registry error around ewant + reflect.DeepCompare?
e
,
ok
:=
err
.
(
*
registryError
)
if
!
(
ok
&&
e
.
Err
==
ewant
&&
osladdr
==
""
)
{
t
.
Fatalf
(
"%s: query %q:
\n
want:
\"\"
, %v
\n
have: %q, %v"
,
r
.
uri
,
hostname
,
ewant
,
osladdr
,
err
)
}
}
else
{
// !error expected
laddr
:=
expect
.
(
string
)
if
!
(
osladdr
==
laddr
&&
err
==
nil
)
{
t
.
Fatalf
(
"%s: query %q:
\n
want: %q, nil
\n
have: %q, %v"
,
r
.
uri
,
hostname
,
laddr
,
osladdr
,
err
)
}
}
}
// announce checks that result of Announce(hostname, osladdr) is as expected.
//
// if len(errv) == 1 - it checks that Announce returns error with cause == errv[0].
// otherwise it will check that Announce succeeds and returns nil error.
announce
:=
func
(
r
*
sqliteRegistry
,
hostname
,
osladdr
string
,
errv
...
error
)
{
t
.
Helper
()
err
:=
r
.
Announce
(
ctx
,
hostname
,
osladdr
)
var
ewant
error
if
len
(
errv
)
>
0
{
ewant
=
errv
[
0
]
if
len
(
errv
)
>
1
{
panic
(
"only 1 error allowed in announce check"
)
}
}
if
ewant
!=
nil
{
// error expected
// XXX construct full registry error around ewant + reflect.DeepCompare?
e
,
ok
:=
err
.
(
*
registryError
)
if
(
!
ok
&&
e
.
Err
==
ewant
)
{
t
.
Fatalf
(
"%s: announce %q %q:
\n
want %v
\n
have: %v"
,
r
.
uri
,
hostname
,
osladdr
,
ewant
,
err
)
}
}
else
{
// !error expected
if
err
!=
nil
{
t
.
Fatalf
(
"%s: announce %q %q: %s"
,
r
.
uri
,
hostname
,
osladdr
,
err
)
}
}
}
ø
:=
errNoHost
// r.Network() == ...
query
(
r
,
"α"
,
ø
)
announce
(
r
,
"α"
,
"alpha:1234"
)
announce
(
r
,
"α"
,
"alpha:1234"
,
errHostDup
)
announce
(
r
,
"α"
,
"alpha:1235"
,
errHostDup
)
query
(
r
,
"α"
,
"alpha:1234"
)
query
(
r
,
"β"
,
ø
)
r2
,
err
:=
openRegistrySQLite
(
ctx
,
dbpath
,
"aaa"
)
// r2.Network() == ...
query
(
r2
,
"α"
,
"alpha:1234"
)
query
(
r2
,
"β"
,
ø
)
announce
(
r2
,
"β"
,
"beta:zzz"
)
query
(
r2
,
"β"
,
"beta:zzz"
)
query
(
r
,
"β"
,
"beta:zzz"
)
X
(
r
.
Close
())
query
(
r
,
"α"
,
errRegistryDown
)
query
(
r
,
"β"
,
errRegistryDown
)
announce
(
r
,
"γ"
,
"gamma:qqq"
,
errRegistryDown
)
query
(
r
,
"γ"
,
errRegistryDown
)
query
(
r2
,
"α"
,
"alpha:1234"
)
X
(
r2
.
Close
())
query
(
r2
,
"α"
,
errRegistryDown
)
// verify network mismatch detection works
r3
,
err
:=
openRegistrySQLite
(
ctx
,
dbpath
,
"bbb"
)
if
!
(
r3
==
nil
&&
err
!=
nil
)
{
t
.
Fatalf
(
"network mismatch: not detected"
)
}
errWant
:=
fmt
.
Sprintf
(
`%s: open []: setup "bbb": network name mismatch: want "bbb"; have "aaa"`
,
dbpath
)
if
err
.
Error
()
!=
errWant
{
t
.
Fatalf
(
"network mismatch: error:
\n
have: %q
\n
want: %q"
,
err
.
Error
(),
errWant
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment