diff --git a/bin/autojump b/bin/autojump index 1d3604b..d88516e 100755 --- a/bin/autojump +++ b/bin/autojump @@ -81,6 +81,7 @@ class Database: else: import math self.data[path] = math.sqrt((self.data[path]**2)+(increment**2)) + self.save() def decay(self): """ @@ -102,34 +103,34 @@ class Database: """ Try to open the database file, recovering from backup if needed. """ - try: - with open(self.filename, 'r') as aj_file: - for line in aj_file.readlines(): + if os.path.exists(self.filename): + with open(self.filename, 'r') as f: + for line in f.readlines(): weight, path = line[:-1].split("\t", 1) path = decode(path, 'utf-8') self.data[path] = float(weight) - except (IOError, EOFError): - if not error_recovery and os.path.exists(self.filename + ".bak"): + elif os.path.exists(self.filename + '.bak'): + if not error_recovery: print('Problem with autojump database,\ trying to recover from backup...', file=sys.stderr) shutil.copy(self.filename + '.bak', self.filename) return self.load(True) else: - # TODO: migration code, will be removed in v22+ - # autojump_py last used in v17 + # migration code, autojump_py last used in v17 self.filename = get_db_file('autojump_py') if os.path.exists(self.filename): try: # fix to get optimised pickle in python < 3 import cPickle as pickle except ImportError: import pickle + try: - with open(self.filename, 'rb') as aj_file: + with open(self.filename, 'rb') as f: # encoding is only specified for Python 2 compatibility if sys.version_info[0] > 2: - self.data = pickle.load(aj_file, encoding="utf-8") + self.data = pickle.load(f, encoding="utf-8") else: - self.data = pickle.load(aj_file) + self.data = pickle.load(f) unicode_dict = {} for k, v in self.data.items(): print(k) @@ -163,7 +164,8 @@ class Database: def save(self): """ - Save database atomically and preserve backup. + Save database atomically and preserve backup, creating new database if + needed. """ # check file existence and permissions if ((not os.path.exists(self.filename)) or @@ -247,7 +249,6 @@ def options(): if(ARGS.add != os.path.expanduser("~")): db = Database(DB_FILE) db.add(decode(ARGS.add)) - db.save() return True if (ARGS.purge): diff --git a/tests/runtests.py b/tests/runtests.py index f25a44a..0381c08 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -6,10 +6,23 @@ from __future__ import division import autojump +import contextlib +import random import os +import shutil +import sys import tempfile import unittest +@contextlib.contextmanager +def no_stderr(): + savestderr = sys.stderr + class DevNull(object): + def write(self, _): pass + sys.stderr = DevNull() + yield + sys.stderr = savestderr + # test suite class TestAutojump(unittest.TestCase): @@ -18,6 +31,8 @@ class TestAutojump(unittest.TestCase): self.fd, self.fname = tempfile.mkstemp() self.db = autojump.Database(self.fname) + random.seed() + def tearDown(self): os.remove(self.fname) if os.path.isfile(self.fname + ".bak"): @@ -42,18 +57,67 @@ class TestAutojump(unittest.TestCase): self.db.decay() self.assertTrue(self.db.get_weight('/1') < 10) + def test_db_load_existing(self): + self.db = autojump.Database('tests/database.txt') + self.assertTrue(len(self.db) > 0) + def test_db_load_empty(self): - pass + # setup + _, fname = tempfile.mkstemp() + db = autojump.Database(fname) + + try: + # test + self.assertEquals(len(self.db), 0) + finally: + # teardown + os.remove(fname) def test_db_load_backup(self): - pass + # setup + fname = '/tmp/autojump_test_db_load_backup_' + str(random.randint(0,32678)) + db = autojump.Database(fname) + db.add('/1') + os.rename(fname, fname + '.bak') + + try: + # test + with no_stderr(): + db = autojump.Database(fname) + self.assertTrue(len(db.data) > 0) + self.assertTrue(os.path.isfile(fname)) + finally: + # teardown + os.remove(fname) + os.remove(fname + '.bak') def test_db_load_migrate(self): - pass - - def test_db_load_existing(self): - self.db = autojump.Database('tests/database.txt') - self.assertTrue(len(self.db) > 0) + ORIG_CONFIG_DIR = autojump.CONFIG_DIR + try: + # setup + CONFIG_DIR = '/tmp/autojump_test_db_load_migrate_' + str(random.randint(0,32678)) + os.mkdir(CONFIG_DIR) + autojump.CONFIG_DIR = CONFIG_DIR + fname = CONFIG_DIR + '/autojump_py' + db = autojump.Database(fname) + db.add('/1') + shutil.copy(fname, fname + '.bak') + db.add('/2') + + # test + missing_fname = '/tmp/autojump_test_db_load_missing_' + str(random.randint(0,32678)) + '.txt' + db = autojump.Database(missing_fname) + + db.add('/3') + self.assertEquals(len(db.data), 3) + + finally: + # teardown + shutil.rmtree(CONFIG_DIR) + os.remove(missing_fname) + os.remove(missing_fname + '.bak') + + autojump.CONFIG_DIR = ORIG_CONFIG_DIR def test_db_purge(self): self.db.add('/1') @@ -61,7 +125,18 @@ class TestAutojump(unittest.TestCase): self.assertEquals(len(self.db), 0) def test_db_save(self): - pass + # setup + fname = '/tmp/autojump_test_db_save_' + str(random.randint(0,32678)) + '.txt' + db = autojump.Database(fname) + + try: + # test + db.save() + self.assertTrue(os.path.isfile(fname)) + finally: + # teardown + os.remove(fname) + os.remove(fname + '.bak') def test_db_trim(self): self.db.add('/1')