Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
Kirill Smelkov
neo
Commits
1b190e2b
Commit
1b190e2b
authored
Jan 22, 2019
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
4eb451a4
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
165 additions
and
43 deletions
+165
-43
go/zodb/import_test.go
go/zodb/import_test.go
+15
-2
go/zodb/persistent.go
go/zodb/persistent.go
+2
-0
go/zodb/persistent_test.go
go/zodb/persistent_test.go
+148
-41
No files found.
go/zodb/
db
_test.go
→
go/zodb/
import
_test.go
View file @
1b190e2b
...
...
@@ -17,7 +17,20 @@
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package
zodb
package
zodb
_test
func
TestDB
()
{
import
(
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/internal/xtesting"
// wks or any other storage cannot be imported from zodb due to cycle
_
"lab.nexedi.com/kirr/neo/go/zodb/wks"
)
// import at runtime few things into zodb, that zodb cannot import itself due to cyclic dependency.
func
init
()
{
//zodb.ZPyCommit = xtesting.ZPyCommit
zodb
.
ZPyCommit
=
func
(
zurl
string
,
at
zodb
.
Tid
,
objv
...
interface
{})
(
zodb
.
Tid
,
error
)
{
return
xtesting
.
ZPyCommit
(
zurl
,
at
)
// XXX + objv
}
}
go/zodb/persistent.go
View file @
1b190e2b
...
...
@@ -286,6 +286,8 @@ var typeTab = make(map[reflect.Type]*zclass) // {} type -> zclass
// - if obj's type was registered (RegisterClass) -- corresponding class.
// - for Broken objects -- ZODB.Broken("<broken-class>").
// - else -- ZODB.Go("<fully-qualified-type(obj)>")
//
// XXX -> IPersistent.ZClass() ?
func
ClassOf
(
obj
IPersistent
)
string
{
zb
,
broken
:=
obj
.
(
*
Broken
)
if
broken
{
...
...
go/zodb/persistent_test.go
View file @
1b190e2b
...
...
@@ -20,10 +20,16 @@
package
zodb
import
(
"context"
"fmt"
"io/ioutil"
"os"
"reflect"
"testing"
"lab.nexedi.com/kirr/neo/go/transaction"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/mem"
"github.com/stretchr/testify/require"
)
...
...
@@ -62,48 +68,58 @@ func init() {
RegisterClassAlias
(
"t.zodb.MyOldObject"
,
"t.zodb.MyObject"
)
}
func
TestPersistent
(
t
*
testing
.
T
)
{
assert
:=
require
.
New
(
t
)
// _checkObj verifies current state of persistent object.
//
// one can bind _checkObj to t via tCheckObj.
func
_checkObj
(
t
testing
.
TB
,
obj
IPersistent
,
jar
*
Connection
,
oid
Oid
,
serial
Tid
,
state
ObjectState
,
refcnt
int32
,
loading
*
loadState
)
{
t
.
Helper
()
xbase
:=
reflect
.
ValueOf
(
obj
)
.
Elem
()
.
FieldByName
(
"Persistent"
)
pbase
:=
xbase
.
Addr
()
.
Interface
()
.
(
*
Persistent
)
// checkObj verifies current state of persistent object.
checkObj
:=
func
(
obj
IPersistent
,
jar
*
Connection
,
oid
Oid
,
serial
Tid
,
state
ObjectState
,
refcnt
int32
,
loading
*
loadState
)
{
badf
:=
func
(
format
string
,
argv
...
interface
{})
{
t
.
Helper
()
xbase
:=
reflect
.
ValueOf
(
obj
)
.
Elem
()
.
FieldByName
(
"Persistent"
)
pbase
:=
xbase
.
Addr
()
.
Interface
()
.
(
*
Persistent
)
msg
:=
fmt
.
Sprintf
(
format
,
argv
...
)
t
.
Fatalf
(
"%#v: %s"
,
obj
,
msg
)
}
badf
:=
func
(
format
string
,
argv
...
interface
{})
{
t
.
Helper
()
msg
:=
fmt
.
Sprintf
(
format
,
argv
...
)
t
.
Fatalf
(
"%#v: %s"
,
obj
,
msg
)
}
zc
:=
pbase
.
zclass
//zc.class
if
typ
:=
reflect
.
TypeOf
(
obj
)
.
Elem
();
typ
!=
zc
.
typ
{
badf
(
"invalid zclass: .typ = %s ; want %s"
,
zc
.
typ
,
typ
)
}
//zc.stateType
zc
:=
pbase
.
zclass
//zc.class
if
typ
:=
reflect
.
TypeOf
(
obj
)
.
Elem
();
typ
!=
zc
.
typ
{
badf
(
"invalid zclass: .typ = %s ; want %s"
,
zc
.
typ
,
typ
)
}
//zc.stateType
if
pbase
.
jar
!=
jar
{
badf
(
"invalid jar"
)
}
if
pbase
.
oid
!=
oid
{
badf
(
"invalid oid: %s ; want %s"
,
pbase
.
oid
,
oid
)
}
if
pbase
.
serial
!=
serial
{
badf
(
"invalid serial: %s ; want %s"
,
pbase
.
serial
,
serial
)
}
if
pbase
.
state
!=
state
{
badf
(
"invalid state: %s ; want %s"
,
pbase
.
state
,
state
)
}
if
pbase
.
refcnt
!=
refcnt
{
badf
(
"invalid refcnt: %s ; want %s"
,
pbase
.
refcnt
,
refcnt
)
}
if
pbase
.
instance
!=
obj
{
badf
(
"base.instance != obj"
)
}
// XXX loading too?
}
if
pbase
.
jar
!=
jar
{
badf
(
"invalid jar"
)
}
if
pbase
.
oid
!=
oid
{
badf
(
"invalid oid: %s ; want %s"
,
pbase
.
oid
,
oid
)
}
if
pbase
.
serial
!=
serial
{
badf
(
"invalid serial: %s ; want %s"
,
pbase
.
serial
,
serial
)
}
if
pbase
.
state
!=
state
{
badf
(
"invalid state: %s ; want %s"
,
pbase
.
state
,
state
)
}
if
pbase
.
refcnt
!=
refcnt
{
badf
(
"invalid refcnt: %s ; want %s"
,
pbase
.
refcnt
,
refcnt
)
}
if
pbase
.
instance
!=
obj
{
badf
(
"base.instance != obj"
)
}
// XXX loading too?
func
tCheckObj
(
t
testing
.
TB
)
func
(
IPersistent
,
*
Connection
,
Oid
,
Tid
,
ObjectState
,
int32
,
*
loadState
)
{
return
func
(
obj
IPersistent
,
jar
*
Connection
,
oid
Oid
,
serial
Tid
,
state
ObjectState
,
refcnt
int32
,
loading
*
loadState
)
{
_checkObj
(
t
,
obj
,
jar
,
oid
,
serial
,
state
,
refcnt
,
loading
)
}
}
// basic Persistent tests without storage.
func
TestPersistentBasic
(
t
*
testing
.
T
)
{
assert
:=
require
.
New
(
t
)
checkObj
:=
tCheckObj
(
t
)
// unknown type -> Broken
xobj
:=
newGhost
(
"t.unknown"
,
10
,
nil
)
...
...
@@ -140,11 +156,102 @@ func TestPersistent(t *testing.T) {
// ClassOf(unregistered-obj)
obj2
:=
&
Unregistered
{}
assert
.
Equal
(
ClassOf
(
obj2
),
`ZODB.Go("lab.nexedi.com/kirr/neo/go/zodb.Unregistered")`
)
}
// zcacheControl is simple live cache control that prevents specified objects
// to be evicted from live cache.
type
zcacheControl
struct
{
keep
[]
Oid
// objects that must not be evicted
}
func
(
cc
*
zcacheControl
)
WantEvict
(
obj
IPersistent
)
bool
{
for
_
,
oid
:=
range
cc
.
keep
{
if
obj
.
POid
()
==
oid
{
return
false
}
}
return
true
}
var
ZPyCommit
func
(
string
,
Tid
,
...
interface
{})
(
Tid
,
error
)
// XXX ZObject
// Persistent tests with storage.
func
TestPersistentDB
(
t
*
testing
.
T
)
{
X
:=
exc
.
Raiseif
assert
:=
require
.
New
(
t
)
checkObj
:=
tCheckObj
(
t
)
work
,
err
:=
ioutil
.
TempDir
(
""
,
"t-persistent"
);
X
(
err
)
defer
func
()
{
err
:=
os
.
RemoveAll
(
work
);
X
(
err
)
}()
zurl
:=
work
+
"/1.fs"
const
oid1
=
1
// XXX
const
oid2
=
2
// XXX create test db via py (change both oid1 & oid2)
// XXX commit1 to test db
at1
,
err
:=
ZPyCommit
(
zurl
,
0
);
X
(
err
)
// XXX data
fmt
.
Printf
(
"AAA %s
\n
"
,
at1
)
ctx
:=
context
.
Background
()
stor
,
err
:=
OpenStorage
(
ctx
,
zurl
,
&
OpenOptions
{
ReadOnly
:
true
});
X
(
err
)
aa
,
err
:=
stor
.
LastTid
(
ctx
);
X
(
err
)
fmt
.
Printf
(
"BBB %s
\n
"
,
aa
)
db
:=
NewDB
(
stor
)
txn1
,
ctx1
:=
transaction
.
New
(
ctx
)
conn1
,
err
:=
db
.
Open
(
ctx1
,
&
ConnOptions
{});
X
(
err
)
// do not evict oid1 from live cache. oid2 is ok to be evicted.
zcache1
:=
conn1
.
Cache
()
zcache1
.
SetControl
(
&
zcacheControl
{[]
Oid
{
oid1
}})
assert
.
Equal
(
conn1
.
At
(),
at1
)
xobj1
,
err
:=
conn1
.
Get
(
ctx1
,
oid1
);
X
(
err
)
xobj2
,
err
:=
conn1
.
Get
(
ctx1
,
oid2
);
X
(
err
)
assert
.
Equal
(
ClassOf
(
xobj1
),
"t.zodb.MyObject"
)
assert
.
Equal
(
ClassOf
(
xobj2
),
"t.zodb.MyObject"
)
obj1
:=
xobj1
.
(
*
MyObject
)
obj2
:=
xobj2
.
(
*
MyObject
)
checkObj
(
obj1
,
conn1
,
oid1
,
InvalidTid
,
GHOST
,
0
,
nil
)
checkObj
(
obj2
,
conn1
,
oid2
,
InvalidTid
,
GHOST
,
0
,
nil
)
// activate: jar has to load, state changes -> uptodate
err
=
obj1
.
PActivate
(
ctx1
);
X
(
err
)
err
=
obj2
.
PActivate
(
ctx1
);
X
(
err
)
checkObj
(
obj1
,
conn1
,
oid1
,
at1
,
UPTODATE
,
1
,
nil
)
checkObj
(
obj2
,
conn1
,
oid2
,
at1
,
UPTODATE
,
1
,
nil
)
// activate again: refcnt++
err
=
obj1
.
PActivate
(
ctx1
);
X
(
err
)
err
=
obj2
.
PActivate
(
ctx1
);
X
(
err
)
checkObj
(
obj1
,
conn1
,
oid1
,
at1
,
UPTODATE
,
2
,
nil
)
checkObj
(
obj2
,
conn1
,
oid2
,
at1
,
UPTODATE
,
2
,
nil
)
// deactivate: refcnt--
obj1
.
PDeactivate
()
obj2
.
PDeactivate
()
checkObj
(
obj1
,
conn1
,
oid1
,
at1
,
UPTODATE
,
1
,
nil
)
checkObj
(
obj2
,
conn1
,
oid2
,
at1
,
UPTODATE
,
1
,
nil
)
// deactivate: state dropped for obj2, obj1 stays in live cache
obj1
.
PDeactivate
()
obj2
.
PDeactivate
()
checkObj
(
obj1
,
conn1
,
oid1
,
at1
,
UPTODATE
,
0
,
nil
)
checkObj
(
obj2
,
conn1
,
oid2
,
InvalidTid
,
GHOST
,
0
,
nil
)
// invalidate: obj1 state dropped
obj1
.
PDeactivate
()
obj2
.
PDeactivate
()
checkObj
(
obj1
,
conn1
,
oid1
,
InvalidTid
,
GHOST
,
0
,
nil
)
checkObj
(
obj2
,
conn1
,
oid2
,
InvalidTid
,
GHOST
,
0
,
nil
)
// TODO activate - jar has to load, state changes
// TODO activate again - refcnt++
// TODO deactivate - refcnt--
// TODO deactivate - state dropped
// TODO invalidate - must be on txn boundary; state dropped
// XXX
txn1
.
Abort
()
}
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