Commit c4dae76e authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent e4ff923f
// Copyright (C) 2017-2019 Nexedi SA and Contributors. // Copyright (C) 2017-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -22,9 +22,12 @@ package xtesting ...@@ -22,9 +22,12 @@ package xtesting
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"net/url"
"os" "os"
"os/exec" "os/exec"
"reflect"
"sync" "sync"
"testing" "testing"
...@@ -128,3 +131,121 @@ func ZPyCommitRaw(zurl string, at zodb.Tid, objv ...ZRawObject) (_ zodb.Tid, err ...@@ -128,3 +131,121 @@ func ZPyCommitRaw(zurl string, at zodb.Tid, objv ...ZRawObject) (_ zodb.Tid, err
return tid, nil return tid, nil
} }
// XXX + ZPyCommitSrv ?
// ---- storage driver tests ----
// TestDrvWatch verifies that storage driver watcher can observe commits done from outside.
func TestDrvWatch(t *testing.T, zurl string, drvOpen zodb.DriverOpener) {
t.Helper()
X := func(err error) {
if err != nil {
t.Fatal(err)
}
}
NeedPy(t, "zodbtools")
u, err := url.Parse(zurl); X(err)
// xcommit commits new transaction into zurl with raw data specified by objv.
xcommit := func(at zodb.Tid, objv ...ZRawObject) zodb.Tid {
t.Helper()
tid, err := ZPyCommitRaw(zurl, at, objv...); X(err)
return tid
}
// force database creation & open zurl at go side
at := xcommit(0, ZRawObject{0, b("data0")})
ctx := context.Background()
watchq := make(chan zodb.Event)
zdrv, at0, err := drvOpen(ctx, u, &zodb.DriverOptions{ReadOnly: true, Watchq: watchq})
if at0 != at {
t.Fatalf("opened @ %s ; want %s", at0, at)
}
checkHead := func(headOk zodb.Tid) {
t.Helper()
head, err := zdrv.Sync(ctx); X(err)
if head != headOk {
t.Fatalf("check head: got %s; want %s", head, headOk)
}
}
checkHead(at)
checkLoad := func(at zodb.Tid, oid zodb.Oid, dataOk string, serialOk zodb.Tid) {
t.Helper()
xid := zodb.Xid{at, oid}
buf, serial, err := zdrv.Load(ctx, xid); X(err)
data := string(buf.XData())
if !(data == dataOk && serial == serialOk) {
t.Fatalf("check load %s:\nhave: %q %s\nwant: %q %s",
xid, data, serial, dataOk, serialOk)
}
}
// commit -> check watcher observes what we committed.
//
// XXX python `import pkg_resources` takes ~ 300ms.
// https://github.com/pypa/setuptools/issues/510
//
// Since pkg_resources are used everywhere (e.g. in zodburi to find all
// uri resolvers) this import slowness becomes the major part of time to
// run py `zodb commit`.
//
// if one day it is either fixed, or worked around, we could ↑ 10 to 100.
for i := zodb.Oid(1); i <= 10; i++ {
data0 := fmt.Sprintf("data0.%d", i)
datai := fmt.Sprintf("data%d", i)
at = xcommit(at,
ZRawObject{0, b(data0)},
ZRawObject{i, b(datai)})
// TODO also test for watcher errors
event := <-watchq
var δ *zodb.EventCommit
switch event := event.(type) {
default:
panic(fmt.Sprintf("unexpected event: %T", event))
case *zodb.EventError:
t.Fatal(event.Err)
case *zodb.EventCommit:
δ = event
}
if objvWant := []zodb.Oid{0, i}; !(δ.Tid == at && reflect.DeepEqual(δ.Changev, objvWant)) {
t.Fatalf("watch:\nhave: %s %s\nwant: %s %s", δ.Tid, δ.Changev, at, objvWant)
}
checkHead(at)
// make sure we can load what was committed.
checkLoad(at, 0, data0, at)
checkLoad(at, i, datai, at)
}
err = zdrv.Close(); X(err)
e, ok := <-watchq
if ok {
t.Fatalf("watch after close -> %v; want closed", e)
}
}
// b is syntatic sugar for byte literals.
//
// e.g.
//
// b("hello")
func b(data string) []byte {
return []byte(data)
}
...@@ -73,14 +73,8 @@ func RegisterDriver(scheme string, opener DriverOpener) { ...@@ -73,14 +73,8 @@ func RegisterDriver(scheme string, opener DriverOpener) {
driverRegistry[scheme] = opener driverRegistry[scheme] = opener
} }
// Open opens ZODB storage by URL. // XXX
// func openDriver(ctx context.Context, zurl string, opt *DriverOptions) (_ IStorageDriver, at0 Tid, _ error) {
// Only URL schemes registered to zodb package are handled.
// Users should import in storage packages they use or zodb/wks package to
// get support for well-known storages.
//
// Storage authors should register their storages with RegisterStorage.
func Open(ctx context.Context, zurl string, opt *OpenOptions) (IStorage, error) {
// no scheme -> file:// // no scheme -> file://
if !strings.Contains(zurl, "://") { if !strings.Contains(zurl, "://") {
zurl = "file://" + zurl zurl = "file://" + zurl
...@@ -88,7 +82,7 @@ func Open(ctx context.Context, zurl string, opt *OpenOptions) (IStorage, error) ...@@ -88,7 +82,7 @@ func Open(ctx context.Context, zurl string, opt *OpenOptions) (IStorage, error)
u, err := url.Parse(zurl) u, err := url.Parse(zurl)
if err != nil { if err != nil {
return nil, err return nil, InvalidTid, err
} }
// XXX commonly handle some options from url -> opt? // XXX commonly handle some options from url -> opt?
...@@ -97,16 +91,32 @@ func Open(ctx context.Context, zurl string, opt *OpenOptions) (IStorage, error) ...@@ -97,16 +91,32 @@ func Open(ctx context.Context, zurl string, opt *OpenOptions) (IStorage, error)
opener, ok := driverRegistry[u.Scheme] opener, ok := driverRegistry[u.Scheme]
if !ok { if !ok {
return nil, fmt.Errorf("zodb: URL scheme \"%s://\" not supported", u.Scheme) return nil, InvalidTid, fmt.Errorf("zodb: URL scheme \"%s://\" not supported", u.Scheme)
}
storDriver, at0, err := opener(ctx, u, opt)
if err != nil {
return nil, InvalidTid, err
} }
return storDriver, at0, nil
}
// Open opens ZODB storage by URL.
//
// Only URL schemes registered to zodb package are handled.
// Users should import in storage packages they use or zodb/wks package to
// get support for well-known storages.
//
// Storage authors should register their storages with RegisterStorage.
func Open(ctx context.Context, zurl string, opt *OpenOptions) (IStorage, error) {
drvWatchq := make(chan Event) drvWatchq := make(chan Event)
drvOpt := &DriverOptions{ drvOpt := &DriverOptions{
ReadOnly: opt.ReadOnly, ReadOnly: opt.ReadOnly,
Watchq: drvWatchq, Watchq: drvWatchq,
} }
storDriver, at0, err := opener(ctx, u, drvOpt) storDriver, at0, err := openDriver(ctx, zurl, drvOpt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
// Copyright (C) 2017-2019 Nexedi SA and Contributors. // Copyright (C) 2017-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -350,6 +350,7 @@ func BenchmarkIterate(b *testing.B) { ...@@ -350,6 +350,7 @@ func BenchmarkIterate(b *testing.B) {
b.StopTimer() b.StopTimer()
} }
/*
// b is syntatic sugar for byte literals. // b is syntatic sugar for byte literals.
// //
// e.g. // e.g.
...@@ -358,9 +359,13 @@ func BenchmarkIterate(b *testing.B) { ...@@ -358,9 +359,13 @@ func BenchmarkIterate(b *testing.B) {
func b(data string) []byte { func b(data string) []byte {
return []byte(data) return []byte(data)
} }
*/
// TestWatch verifies that watcher can observe commits done from outside. // TestWatch verifies that watcher can observe commits done from outside.
func TestWatch(t *testing.T) { func TestWatch(t *testing.T) {
workdir := xworkdir(t)
xtesting.TestDrvWatch(t, workdir + "/t.fs", openByURL)
/*
X := exc.Raiseif X := exc.Raiseif
xtesting.NeedPy(t, "zodbtools") xtesting.NeedPy(t, "zodbtools")
...@@ -454,6 +459,7 @@ func TestWatch(t *testing.T) { ...@@ -454,6 +459,7 @@ func TestWatch(t *testing.T) {
if ok { if ok {
t.Fatalf("watch after close -> %v; want closed", e) t.Fatalf("watch after close -> %v; want closed", e)
} }
*/
} }
// TestOpenRecovery verifies how Open handles data file with not-finished voted // TestOpenRecovery verifies how Open handles data file with not-finished voted
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment