mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 06:52:21 -04:00
some initial sync work
This commit is contained in:
parent
6627264079
commit
91efb8f30b
3 changed files with 645 additions and 878 deletions
902
anki/sync.py
902
anki/sync.py
File diff suppressed because it is too large
Load diff
|
@ -1,293 +0,0 @@
|
||||||
# coding: utf-8
|
|
||||||
|
|
||||||
import nose, os, tempfile, shutil, time
|
|
||||||
from tests.shared import assertException
|
|
||||||
|
|
||||||
from anki.errors import *
|
|
||||||
from anki import Deck
|
|
||||||
from anki.db import *
|
|
||||||
from anki.stdmodels import BasicModel
|
|
||||||
from anki.sync import SyncClient, SyncServer, HttpSyncServer, HttpSyncServerProxy
|
|
||||||
from anki.sync import copyLocalMedia
|
|
||||||
from anki.facts import Fact
|
|
||||||
from anki.cards import Card
|
|
||||||
from anki.models import FieldModel
|
|
||||||
from anki.media import rebuildMediaDir
|
|
||||||
|
|
||||||
#import psyco; psyco.profile()
|
|
||||||
|
|
||||||
# Local tests
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
deck1=None
|
|
||||||
deck2=None
|
|
||||||
client=None
|
|
||||||
server=None
|
|
||||||
|
|
||||||
def setup_local(loadDecks=None):
|
|
||||||
global deck1, deck2, client, server
|
|
||||||
if loadDecks:
|
|
||||||
deck1 = Deck(loadDecks[0], backup=False)
|
|
||||||
deck2 = Deck(loadDecks[1], backup=False)
|
|
||||||
else:
|
|
||||||
deck1 = Deck()
|
|
||||||
deck1.addModel(BasicModel())
|
|
||||||
deck1.currentModel.cardModels[1].active = True
|
|
||||||
deck1.newCardOrder = 1
|
|
||||||
f = deck1.newFact()
|
|
||||||
f['Front'] = u"foo"; f['Back'] = u"bar"; f.tags = u"foo"
|
|
||||||
deck1.addFact(f)
|
|
||||||
deck2 = Deck()
|
|
||||||
deck2.addModel(BasicModel())
|
|
||||||
deck2.currentModel.cardModels[1].active = True
|
|
||||||
f = deck2.newFact()
|
|
||||||
f['Front'] = u"baz"; f['Back'] = u"qux"; f.tags = u"bar"
|
|
||||||
deck2.addFact(f)
|
|
||||||
deck2.newCardOrder = 1
|
|
||||||
# normally such syncs would trigger a conflict, but we ignore it
|
|
||||||
deck1.setVar("schemaMod", 0)
|
|
||||||
deck2.setVar("schemaMod", 0)
|
|
||||||
client = SyncClient(deck1)
|
|
||||||
server = SyncServer(deck2)
|
|
||||||
client.setServer(server)
|
|
||||||
|
|
||||||
def teardown():
|
|
||||||
pass
|
|
||||||
|
|
||||||
@nose.with_setup(setup_local, teardown)
|
|
||||||
def test_localsync_diffing():
|
|
||||||
assert deck1.cardCount() == 2
|
|
||||||
assert deck2.cardCount() == 2
|
|
||||||
lsum = client.summary(deck1.lastSync)
|
|
||||||
rsum = server.summary(deck1.lastSync)
|
|
||||||
result = client.diffSummary(lsum, rsum, 'cards')
|
|
||||||
assert len(result[0]) == 2
|
|
||||||
assert len(result[1]) == 0
|
|
||||||
assert len(result[2]) == 2
|
|
||||||
assert len(result[3]) == 0
|
|
||||||
result = client.diffSummary(lsum, rsum, 'facts')
|
|
||||||
assert len(result[0]) == 1
|
|
||||||
assert len(result[1]) == 0
|
|
||||||
assert len(result[2]) == 1
|
|
||||||
assert len(result[3]) == 0
|
|
||||||
|
|
||||||
@nose.with_setup(setup_local, teardown)
|
|
||||||
def test_localsync_deck():
|
|
||||||
# deck two was modified last
|
|
||||||
assert deck2.modified > deck1.modified
|
|
||||||
d2mod = deck2.modified
|
|
||||||
assert deck1.lastSync == 0 and deck2.lastSync == 0
|
|
||||||
client.sync()
|
|
||||||
assert deck1.modified == deck2.modified
|
|
||||||
assert deck1.modified <= deck1.lastSync
|
|
||||||
assert deck1.lastSync == deck2.lastSync
|
|
||||||
# ensure values are being synced
|
|
||||||
deck1.lowPriority += u",foo"
|
|
||||||
deck1.setModified()
|
|
||||||
client.sync()
|
|
||||||
assert "foo" in deck2.lowPriority
|
|
||||||
assert deck1.modified == deck2.modified
|
|
||||||
assert deck1.lastSync == deck2.lastSync
|
|
||||||
deck2.description = u"newname"
|
|
||||||
deck2.setModified()
|
|
||||||
client.sync()
|
|
||||||
assert deck1.description == u"newname"
|
|
||||||
# the most recent change should take precedence
|
|
||||||
deck1.description = u"foo"
|
|
||||||
deck1.setModified()
|
|
||||||
deck2.description = u"bar"
|
|
||||||
deck2.setModified()
|
|
||||||
client.sync()
|
|
||||||
assert deck1.description == "bar"
|
|
||||||
# answer a card to ensure stats & history are copied
|
|
||||||
c = deck1.getCard()
|
|
||||||
deck1.answerCard(c, 4)
|
|
||||||
client.sync()
|
|
||||||
assert deck2.db.scalar("select count(*) from revlog") == 1
|
|
||||||
# make sure meta data is synced
|
|
||||||
deck1.setVar("foo", 1)
|
|
||||||
assert deck1.getInt("foo") == 1
|
|
||||||
assert deck2.getInt("foo") is None
|
|
||||||
client.sync()
|
|
||||||
assert deck1.getInt("foo") == 1
|
|
||||||
assert deck2.getInt("foo") == 1
|
|
||||||
|
|
||||||
@nose.with_setup(setup_local, teardown)
|
|
||||||
def test_localsync_models():
|
|
||||||
client.sync()
|
|
||||||
# add a model
|
|
||||||
deck1.addModel(BasicModel())
|
|
||||||
assert len(deck1.models) == 3
|
|
||||||
assert len(deck2.models) == 2
|
|
||||||
deck1.setVar("schemaMod", 0)
|
|
||||||
client.sync()
|
|
||||||
assert len(deck2.models) == 3
|
|
||||||
assert deck1.currentModel.id == deck2.currentModel.id
|
|
||||||
# delete the recently added model
|
|
||||||
deck2.deleteModel(deck2.currentModel)
|
|
||||||
assert len(deck2.models) == 2
|
|
||||||
deck2.setVar("schemaMod", 0)
|
|
||||||
client.sync()
|
|
||||||
assert len(deck1.models) == 2
|
|
||||||
assert deck1.currentModel.id == deck2.currentModel.id
|
|
||||||
# make a card model inactive
|
|
||||||
assert deck1.currentModel.cardModels[1].active == True
|
|
||||||
deck2.currentModel.cardModels[1].active = False
|
|
||||||
deck2.currentModel.setModified()
|
|
||||||
deck2.flushMod()
|
|
||||||
client.sync()
|
|
||||||
assert deck1.currentModel.cardModels[1].active == False
|
|
||||||
# remove a card model
|
|
||||||
deck1.deleteCardModel(deck1.currentModel,
|
|
||||||
deck1.currentModel.cardModels[1])
|
|
||||||
deck1.currentModel.setModified()
|
|
||||||
deck1.setModified()
|
|
||||||
assert len(deck1.currentModel.cardModels) == 1
|
|
||||||
deck1.setVar("schemaMod", 0)
|
|
||||||
client.sync()
|
|
||||||
assert len(deck2.currentModel.cardModels) == 1
|
|
||||||
# rename a field
|
|
||||||
c = deck1.getCard()
|
|
||||||
assert u"Front" in c.fact.keys()
|
|
||||||
deck1.renameFieldModel(deck1.currentModel,
|
|
||||||
deck1.currentModel.fieldModels[0],
|
|
||||||
u"Sideways")
|
|
||||||
client.sync()
|
|
||||||
assert deck2.currentModel.fieldModels[0].name == u"Sideways"
|
|
||||||
|
|
||||||
@nose.with_setup(setup_local, teardown)
|
|
||||||
def test_localsync_factsandcards():
|
|
||||||
assert deck1.factCount() == 1 and deck1.cardCount() == 2
|
|
||||||
assert deck2.factCount() == 1 and deck2.cardCount() == 2
|
|
||||||
client.sync()
|
|
||||||
deck1.reset(); deck2.reset()
|
|
||||||
assert deck1.factCount() == 2 and deck1.cardCount() == 4
|
|
||||||
assert deck2.factCount() == 2 and deck2.cardCount() == 4
|
|
||||||
# ensure the fact was copied across
|
|
||||||
f1 = deck1.db.query(Fact).first()
|
|
||||||
f2 = deck1.db.query(Fact).get(f1.id)
|
|
||||||
f1['Front'] = u"myfront"
|
|
||||||
f1.setModified()
|
|
||||||
deck1.setModified()
|
|
||||||
client.sync()
|
|
||||||
deck1.rebuildCounts()
|
|
||||||
deck2.rebuildCounts()
|
|
||||||
f2 = deck1.db.query(Fact).get(f1.id)
|
|
||||||
assert f2['Front'] == u"myfront"
|
|
||||||
c1 = deck1.getCard()
|
|
||||||
c2 = deck2.getCard()
|
|
||||||
assert c1.id == c2.id
|
|
||||||
|
|
||||||
@nose.with_setup(setup_local, teardown)
|
|
||||||
def test_localsync_threeway():
|
|
||||||
# deck1 (client) <-> deck2 (server) <-> deck3 (client)
|
|
||||||
deck3 = Deck()
|
|
||||||
client2 = SyncClient(deck3)
|
|
||||||
server2 = SyncServer(deck2)
|
|
||||||
client2.setServer(server2)
|
|
||||||
client.sync()
|
|
||||||
client2.sync()
|
|
||||||
# add a new question
|
|
||||||
f = deck1.newFact()
|
|
||||||
f['Front'] = u"a"; f['Back'] = u"b"
|
|
||||||
f = deck1.addFact(f)
|
|
||||||
card = f.cards[0]
|
|
||||||
client.sync()
|
|
||||||
assert deck1.cardCount() == 6
|
|
||||||
assert deck2.cardCount() == 6
|
|
||||||
# check it propagates from server to deck3
|
|
||||||
client2.sync()
|
|
||||||
assert deck3.cardCount() == 6
|
|
||||||
# delete a card on deck1
|
|
||||||
deck1.deleteCard(card.id)
|
|
||||||
client.sync()
|
|
||||||
deck1.reset(); deck2.reset()
|
|
||||||
assert deck1.cardCount() == 5
|
|
||||||
assert deck2.cardCount() == 5
|
|
||||||
# make sure the delete is now propagated from the server to deck3
|
|
||||||
client2.sync()
|
|
||||||
assert deck3.cardCount() == 5
|
|
||||||
|
|
||||||
def test_localsync_media():
|
|
||||||
tmpdir = "/tmp/media-tests"
|
|
||||||
try:
|
|
||||||
shutil.rmtree(tmpdir)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
shutil.copytree(os.path.join(os.path.dirname(__file__), "..",
|
|
||||||
"tests/syncing/media-tests"),
|
|
||||||
tmpdir)
|
|
||||||
deck1anki = os.path.join(tmpdir, "1.anki")
|
|
||||||
deck2anki = os.path.join(tmpdir, "2.anki")
|
|
||||||
deck1media = os.path.join(tmpdir, "1.media")
|
|
||||||
deck2media = os.path.join(tmpdir, "2.media")
|
|
||||||
setup_local((deck1anki, deck2anki))
|
|
||||||
assert len(os.listdir(deck1media)) == 2
|
|
||||||
assert len(os.listdir(deck2media)) == 1
|
|
||||||
client.sync()
|
|
||||||
# metadata should have been copied
|
|
||||||
assert deck1.db.scalar("select count(1) from media") == 3
|
|
||||||
assert deck2.db.scalar("select count(1) from media") == 3
|
|
||||||
# copy local files
|
|
||||||
copyLocalMedia(deck1, deck2)
|
|
||||||
assert len(os.listdir(deck1media)) == 2
|
|
||||||
assert len(os.listdir(deck2media)) == 3
|
|
||||||
copyLocalMedia(deck2, deck1)
|
|
||||||
assert len(os.listdir(deck1media)) == 3
|
|
||||||
assert len(os.listdir(deck2media)) == 3
|
|
||||||
# check delete
|
|
||||||
os.unlink(os.path.join(deck1media, "22161b29b0c18e068038021f54eee1ee.png"))
|
|
||||||
rebuildMediaDir(deck1)
|
|
||||||
client.sync()
|
|
||||||
assert deck1.db.scalar("select count(1) from media") == 3
|
|
||||||
assert deck2.db.scalar("select count(1) from media") == 3
|
|
||||||
|
|
||||||
# Remote tests
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
# a replacement runCmd which just calls our server directly
|
|
||||||
def runCmd(action, *args, **kargs):
|
|
||||||
#print action, kargs
|
|
||||||
return server.unstuff(apply(getattr(server, action), tuple(args) +
|
|
||||||
tuple(kargs.values())))
|
|
||||||
|
|
||||||
def setup_remote():
|
|
||||||
setup_local()
|
|
||||||
global client, server
|
|
||||||
proxy = HttpSyncServerProxy("test", "foo")
|
|
||||||
client = SyncClient(deck1)
|
|
||||||
client.setServer(proxy)
|
|
||||||
proxy.deckName = "test"
|
|
||||||
proxy.runCmd = runCmd
|
|
||||||
server = HttpSyncServer()
|
|
||||||
server.deck = deck2
|
|
||||||
server.decks = {"test": (deck2.modified, 0)}
|
|
||||||
|
|
||||||
@nose.with_setup(setup_remote, teardown)
|
|
||||||
def test_remotesync_fromserver():
|
|
||||||
# deck two was modified last
|
|
||||||
assert deck2.modified > deck1.modified
|
|
||||||
client.sync()
|
|
||||||
assert deck2.modified == deck1.modified
|
|
||||||
# test deck vars
|
|
||||||
deck1.setVar("foo", 1)
|
|
||||||
client.sync()
|
|
||||||
|
|
||||||
@nose.with_setup(setup_remote, teardown)
|
|
||||||
def test_remotesync_toserver():
|
|
||||||
deck1.setModified()
|
|
||||||
client.sync()
|
|
||||||
assert deck2.modified == deck1.modified
|
|
||||||
|
|
||||||
# Full sync
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
@nose.with_setup(setup_remote, teardown)
|
|
||||||
def test_formdata():
|
|
||||||
global deck1
|
|
||||||
(fd, name) = tempfile.mkstemp()
|
|
||||||
deck1 = deck1.saveAs(name)
|
|
||||||
deck1.setModified()
|
|
||||||
client.deck = deck1
|
|
||||||
client.prepareSync(0)
|
|
||||||
client.prepareFullSync()
|
|
328
tests/test_sync.py
Normal file
328
tests/test_sync.py
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
import nose, os, tempfile, shutil, time
|
||||||
|
from tests.shared import assertException
|
||||||
|
|
||||||
|
from anki.errors import *
|
||||||
|
from anki import Deck
|
||||||
|
from anki.utils import intTime
|
||||||
|
from anki.stdmodels import BasicModel
|
||||||
|
from anki.sync import SyncClient, SyncServer, HttpSyncServer, HttpSyncServerProxy
|
||||||
|
from anki.sync import copyLocalMedia
|
||||||
|
from anki.facts import Fact
|
||||||
|
from anki.cards import Card
|
||||||
|
from tests.shared import getEmptyDeck
|
||||||
|
|
||||||
|
#import psyco; psyco.profile()
|
||||||
|
|
||||||
|
# Local tests
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
deck1=None
|
||||||
|
deck2=None
|
||||||
|
client=None
|
||||||
|
server=None
|
||||||
|
|
||||||
|
def setup_local(loadDecks=None):
|
||||||
|
global deck1, deck2, client, server
|
||||||
|
if loadDecks:
|
||||||
|
deck1 = Deck(loadDecks[0], backup=False)
|
||||||
|
deck2 = Deck(loadDecks[1], backup=False)
|
||||||
|
else:
|
||||||
|
deck1 = getEmptyDeck()
|
||||||
|
f = deck1.newFact()
|
||||||
|
f['Front'] = u"foo"; f['Back'] = u"bar"; f.tags = [u"foo"]
|
||||||
|
deck1.addFact(f)
|
||||||
|
deck1.syncName = "abc"
|
||||||
|
deck2 = getEmptyDeck()
|
||||||
|
f = deck2.newFact()
|
||||||
|
f['Front'] = u"foo"; f['Back'] = u"bar"; f.tags = [u"foo"]
|
||||||
|
deck2.addFact(f)
|
||||||
|
deck2.syncName = "abc"
|
||||||
|
deck1.lastSync = deck2.lastSync = intTime()
|
||||||
|
deck1.scm = deck2.scm = 0
|
||||||
|
time.sleep(1)
|
||||||
|
# now add another fact to deck1 that hasn't been synced yet
|
||||||
|
f = deck1.newFact()
|
||||||
|
f['Front'] = u"bar"; f['Back'] = u"baz"
|
||||||
|
deck1.addFact(f)
|
||||||
|
# and another to deck2
|
||||||
|
f = deck2.newFact()
|
||||||
|
f['Front'] = u"qux"; f['Back'] = u"baz"
|
||||||
|
deck2.addFact(f)
|
||||||
|
deck2.reset()
|
||||||
|
c = deck2.sched.getCard()
|
||||||
|
deck2.sched.answerCard(c, 3)
|
||||||
|
# change deck1's model
|
||||||
|
deck1.currentModel().flush()
|
||||||
|
deck1.save(); deck2.save()
|
||||||
|
client = SyncClient(deck1)
|
||||||
|
server = SyncServer(deck2)
|
||||||
|
print "deck1", client.deck.db.all("select * from facts")
|
||||||
|
print "deck2", server.deck.db.all("select * from facts")
|
||||||
|
client.setServer(server)
|
||||||
|
|
||||||
|
def teardown():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@nose.with_setup(setup_local, teardown)
|
||||||
|
def test_changes():
|
||||||
|
deck2.scm = 0
|
||||||
|
dels = client.deletions(deck1.lastSync)
|
||||||
|
rem = server.changes(deck1.lastSync, dels)
|
||||||
|
client.delete(rem['deletions'])
|
||||||
|
assert rem
|
||||||
|
client.rewriteIds(rem)
|
||||||
|
loc = client.changes(deck1.lastSync)
|
||||||
|
assert loc
|
||||||
|
l, r = client.diff(loc, rem, "facts", 3)
|
||||||
|
# local id is larger
|
||||||
|
assert l[0][0] == 3
|
||||||
|
assert r[0][0] == 2
|
||||||
|
|
||||||
|
keys = ("models", "groups", "gconf", "facts", "cards")
|
||||||
|
keys2 = ("revlog", "tags")
|
||||||
|
|
||||||
|
proc = {}
|
||||||
|
resp = {}
|
||||||
|
for type in keys:
|
||||||
|
l, r = getattr(client, 'diff'+type.capitalize())(loc, rem)
|
||||||
|
proc[type] = r
|
||||||
|
resp[type] = l
|
||||||
|
for type in keys2:
|
||||||
|
l = loc[type]; r = rem[type]
|
||||||
|
proc[type] = r
|
||||||
|
resp[type] = l
|
||||||
|
|
||||||
|
for type in keys + keys2:
|
||||||
|
getattr(client, 'update'+type.capitalize())(proc[type])
|
||||||
|
|
||||||
|
for type in keys + keys2:
|
||||||
|
getattr(server, 'update'+type.capitalize())(resp[type])
|
||||||
|
|
||||||
|
print "deck1", client.deck.db.all("select * from revlog")
|
||||||
|
print "deck2", server.deck.db.all("select * from revlog")
|
||||||
|
|
||||||
|
#client.process(loc, rem)
|
||||||
|
|
||||||
|
|
||||||
|
# @nose.with_setup(setup_local, teardown)
|
||||||
|
# def test_localsync_deck():
|
||||||
|
# # deck two was modified last
|
||||||
|
# assert deck2.modified > deck1.modified
|
||||||
|
# d2mod = deck2.modified
|
||||||
|
# assert deck1.lastSync == 0 and deck2.lastSync == 0
|
||||||
|
# client.sync()
|
||||||
|
# assert deck1.modified == deck2.modified
|
||||||
|
# assert deck1.modified <= deck1.lastSync
|
||||||
|
# assert deck1.lastSync == deck2.lastSync
|
||||||
|
# # ensure values are being synced
|
||||||
|
# deck1.lowPriority += u",foo"
|
||||||
|
# deck1.setModified()
|
||||||
|
# client.sync()
|
||||||
|
# assert "foo" in deck2.lowPriority
|
||||||
|
# assert deck1.modified == deck2.modified
|
||||||
|
# assert deck1.lastSync == deck2.lastSync
|
||||||
|
# deck2.description = u"newname"
|
||||||
|
# deck2.setModified()
|
||||||
|
# client.sync()
|
||||||
|
# assert deck1.description == u"newname"
|
||||||
|
# # the most recent change should take precedence
|
||||||
|
# deck1.description = u"foo"
|
||||||
|
# deck1.setModified()
|
||||||
|
# deck2.description = u"bar"
|
||||||
|
# deck2.setModified()
|
||||||
|
# client.sync()
|
||||||
|
# assert deck1.description == "bar"
|
||||||
|
# # answer a card to ensure stats & history are copied
|
||||||
|
# c = deck1.getCard()
|
||||||
|
# deck1.answerCard(c, 4)
|
||||||
|
# client.sync()
|
||||||
|
# assert deck2.db.scalar("select count(*) from revlog") == 1
|
||||||
|
# # make sure meta data is synced
|
||||||
|
# deck1.setVar("foo", 1)
|
||||||
|
# assert deck1.getInt("foo") == 1
|
||||||
|
# assert deck2.getInt("foo") is None
|
||||||
|
# client.sync()
|
||||||
|
# assert deck1.getInt("foo") == 1
|
||||||
|
# assert deck2.getInt("foo") == 1
|
||||||
|
|
||||||
|
# @nose.with_setup(setup_local, teardown)
|
||||||
|
# def test_localsync_models():
|
||||||
|
# client.sync()
|
||||||
|
# # add a model
|
||||||
|
# deck1.addModel(BasicModel())
|
||||||
|
# assert len(deck1.models) == 3
|
||||||
|
# assert len(deck2.models) == 2
|
||||||
|
# deck1.setVar("schemaMod", 0)
|
||||||
|
# client.sync()
|
||||||
|
# assert len(deck2.models) == 3
|
||||||
|
# assert deck1.currentModel.id == deck2.currentModel.id
|
||||||
|
# # delete the recently added model
|
||||||
|
# deck2.deleteModel(deck2.currentModel)
|
||||||
|
# assert len(deck2.models) == 2
|
||||||
|
# deck2.setVar("schemaMod", 0)
|
||||||
|
# client.sync()
|
||||||
|
# assert len(deck1.models) == 2
|
||||||
|
# assert deck1.currentModel.id == deck2.currentModel.id
|
||||||
|
# # make a card model inactive
|
||||||
|
# assert deck1.currentModel.cardModels[1].active == True
|
||||||
|
# deck2.currentModel.cardModels[1].active = False
|
||||||
|
# deck2.currentModel.setModified()
|
||||||
|
# deck2.flushMod()
|
||||||
|
# client.sync()
|
||||||
|
# assert deck1.currentModel.cardModels[1].active == False
|
||||||
|
# # remove a card model
|
||||||
|
# deck1.deleteCardModel(deck1.currentModel,
|
||||||
|
# deck1.currentModel.cardModels[1])
|
||||||
|
# deck1.currentModel.setModified()
|
||||||
|
# deck1.setModified()
|
||||||
|
# assert len(deck1.currentModel.cardModels) == 1
|
||||||
|
# deck1.setVar("schemaMod", 0)
|
||||||
|
# client.sync()
|
||||||
|
# assert len(deck2.currentModel.cardModels) == 1
|
||||||
|
# # rename a field
|
||||||
|
# c = deck1.getCard()
|
||||||
|
# assert u"Front" in c.fact.keys()
|
||||||
|
# deck1.renameFieldModel(deck1.currentModel,
|
||||||
|
# deck1.currentModel.fieldModels[0],
|
||||||
|
# u"Sideways")
|
||||||
|
# client.sync()
|
||||||
|
# assert deck2.currentModel.fieldModels[0].name == u"Sideways"
|
||||||
|
|
||||||
|
# @nose.with_setup(setup_local, teardown)
|
||||||
|
# def test_localsync_factsandcards():
|
||||||
|
# assert deck1.factCount() == 1 and deck1.cardCount() == 2
|
||||||
|
# assert deck2.factCount() == 1 and deck2.cardCount() == 2
|
||||||
|
# client.sync()
|
||||||
|
# deck1.reset(); deck2.reset()
|
||||||
|
# assert deck1.factCount() == 2 and deck1.cardCount() == 4
|
||||||
|
# assert deck2.factCount() == 2 and deck2.cardCount() == 4
|
||||||
|
# # ensure the fact was copied across
|
||||||
|
# f1 = deck1.db.query(Fact).first()
|
||||||
|
# f2 = deck1.db.query(Fact).get(f1.id)
|
||||||
|
# f1['Front'] = u"myfront"
|
||||||
|
# f1.setModified()
|
||||||
|
# deck1.setModified()
|
||||||
|
# client.sync()
|
||||||
|
# deck1.rebuildCounts()
|
||||||
|
# deck2.rebuildCounts()
|
||||||
|
# f2 = deck1.db.query(Fact).get(f1.id)
|
||||||
|
# assert f2['Front'] == u"myfront"
|
||||||
|
# c1 = deck1.getCard()
|
||||||
|
# c2 = deck2.getCard()
|
||||||
|
# assert c1.id == c2.id
|
||||||
|
|
||||||
|
# @nose.with_setup(setup_local, teardown)
|
||||||
|
# def test_localsync_threeway():
|
||||||
|
# # deck1 (client) <-> deck2 (server) <-> deck3 (client)
|
||||||
|
# deck3 = Deck()
|
||||||
|
# client2 = SyncClient(deck3)
|
||||||
|
# server2 = SyncServer(deck2)
|
||||||
|
# client2.setServer(server2)
|
||||||
|
# client.sync()
|
||||||
|
# client2.sync()
|
||||||
|
# # add a new question
|
||||||
|
# f = deck1.newFact()
|
||||||
|
# f['Front'] = u"a"; f['Back'] = u"b"
|
||||||
|
# f = deck1.addFact(f)
|
||||||
|
# card = f.cards[0]
|
||||||
|
# client.sync()
|
||||||
|
# assert deck1.cardCount() == 6
|
||||||
|
# assert deck2.cardCount() == 6
|
||||||
|
# # check it propagates from server to deck3
|
||||||
|
# client2.sync()
|
||||||
|
# assert deck3.cardCount() == 6
|
||||||
|
# # delete a card on deck1
|
||||||
|
# deck1.deleteCard(card.id)
|
||||||
|
# client.sync()
|
||||||
|
# deck1.reset(); deck2.reset()
|
||||||
|
# assert deck1.cardCount() == 5
|
||||||
|
# assert deck2.cardCount() == 5
|
||||||
|
# # make sure the delete is now propagated from the server to deck3
|
||||||
|
# client2.sync()
|
||||||
|
# assert deck3.cardCount() == 5
|
||||||
|
|
||||||
|
# def test_localsync_media():
|
||||||
|
# tmpdir = "/tmp/media-tests"
|
||||||
|
# try:
|
||||||
|
# shutil.rmtree(tmpdir)
|
||||||
|
# except OSError:
|
||||||
|
# pass
|
||||||
|
# shutil.copytree(os.path.join(os.path.dirname(__file__), "..",
|
||||||
|
# "tests/syncing/media-tests"),
|
||||||
|
# tmpdir)
|
||||||
|
# deck1anki = os.path.join(tmpdir, "1.anki")
|
||||||
|
# deck2anki = os.path.join(tmpdir, "2.anki")
|
||||||
|
# deck1media = os.path.join(tmpdir, "1.media")
|
||||||
|
# deck2media = os.path.join(tmpdir, "2.media")
|
||||||
|
# setup_local((deck1anki, deck2anki))
|
||||||
|
# assert len(os.listdir(deck1media)) == 2
|
||||||
|
# assert len(os.listdir(deck2media)) == 1
|
||||||
|
# client.sync()
|
||||||
|
# # metadata should have been copied
|
||||||
|
# assert deck1.db.scalar("select count(1) from media") == 3
|
||||||
|
# assert deck2.db.scalar("select count(1) from media") == 3
|
||||||
|
# # copy local files
|
||||||
|
# copyLocalMedia(deck1, deck2)
|
||||||
|
# assert len(os.listdir(deck1media)) == 2
|
||||||
|
# assert len(os.listdir(deck2media)) == 3
|
||||||
|
# copyLocalMedia(deck2, deck1)
|
||||||
|
# assert len(os.listdir(deck1media)) == 3
|
||||||
|
# assert len(os.listdir(deck2media)) == 3
|
||||||
|
# # check delete
|
||||||
|
# os.unlink(os.path.join(deck1media, "22161b29b0c18e068038021f54eee1ee.png"))
|
||||||
|
# rebuildMediaDir(deck1)
|
||||||
|
# client.sync()
|
||||||
|
# assert deck1.db.scalar("select count(1) from media") == 3
|
||||||
|
# assert deck2.db.scalar("select count(1) from media") == 3
|
||||||
|
|
||||||
|
# # Remote tests
|
||||||
|
# ##########################################################################
|
||||||
|
|
||||||
|
# # a replacement runCmd which just calls our server directly
|
||||||
|
# def runCmd(action, *args, **kargs):
|
||||||
|
# #print action, kargs
|
||||||
|
# return server.unstuff(apply(getattr(server, action), tuple(args) +
|
||||||
|
# tuple(kargs.values())))
|
||||||
|
|
||||||
|
# def setup_remote():
|
||||||
|
# setup_local()
|
||||||
|
# global client, server
|
||||||
|
# proxy = HttpSyncServerProxy("test", "foo")
|
||||||
|
# client = SyncClient(deck1)
|
||||||
|
# client.setServer(proxy)
|
||||||
|
# proxy.deckName = "test"
|
||||||
|
# proxy.runCmd = runCmd
|
||||||
|
# server = HttpSyncServer()
|
||||||
|
# server.deck = deck2
|
||||||
|
# server.decks = {"test": (deck2.modified, 0)}
|
||||||
|
|
||||||
|
# @nose.with_setup(setup_remote, teardown)
|
||||||
|
# def test_remotesync_fromserver():
|
||||||
|
# # deck two was modified last
|
||||||
|
# assert deck2.modified > deck1.modified
|
||||||
|
# client.sync()
|
||||||
|
# assert deck2.modified == deck1.modified
|
||||||
|
# # test deck vars
|
||||||
|
# deck1.setVar("foo", 1)
|
||||||
|
# client.sync()
|
||||||
|
|
||||||
|
# @nose.with_setup(setup_remote, teardown)
|
||||||
|
# def test_remotesync_toserver():
|
||||||
|
# deck1.setModified()
|
||||||
|
# client.sync()
|
||||||
|
# assert deck2.modified == deck1.modified
|
||||||
|
|
||||||
|
# # Full sync
|
||||||
|
# ##########################################################################
|
||||||
|
|
||||||
|
# @nose.with_setup(setup_remote, teardown)
|
||||||
|
# def test_formdata():
|
||||||
|
# global deck1
|
||||||
|
# (fd, name) = tempfile.mkstemp()
|
||||||
|
# deck1 = deck1.saveAs(name)
|
||||||
|
# deck1.setModified()
|
||||||
|
# client.deck = deck1
|
||||||
|
# client.prepareSync(0)
|
||||||
|
# client.prepareFullSync()
|
Loading…
Reference in a new issue