summary refs log tree commit diff stats
path: root/test/tc_bookmarks.py
blob: f45ba0614fe9299cc23a477cace19feb11b4d11c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

if __name__ == '__main__': from __init__ import init; init()

from os.path import realpath, join, dirname
import unittest
import os
import time

from ranger.container.bookmarks import Bookmarks

TESTDIR = realpath(join(dirname(__file__), 'testdir'))
BMFILE = join(TESTDIR, 'bookmarks')

class TestDisplayable(unittest.TestCase):
	def setUp(self):
		try:
			os.remove(BMFILE)
		except:
			pass

	def tearDown(self):
		try:
			os.remove(BMFILE)
		except:
			pass
	
	def test_adding_bookmarks(self):
		bm = Bookmarks(BMFILE, str, autosave=False)
		bm.load()
		bm['a'] = 'fooo'
		self.assertEqual(bm['a'], 'fooo')

	def test_sharing_bookmarks_between_instances(self):
		bm = Bookmarks(BMFILE, str, autosave=True)
		bm2 = Bookmarks(BMFILE, str, autosave=True)

		bm.load()
		bm2.load()
		bm['a'] = 'fooo'
		self.assertRaises(KeyError, bm2.__getitem__, 'a')

		bm.save()
		bm2.load()
		self.assertEqual(bm['a'], bm2['a'])

		bm2['a'] = 'bar'

		bm.save()
		bm2.save()
		bm.load()
		bm2.load()

		self.assertEqual(bm['a'], bm2['a'])
	
	def test_messing_around(self):
		bm = Bookmarks(BMFILE, str, autosave=False)
		bm2 = Bookmarks(BMFILE, str, autosave=False)

		bm.load()
		bm['a'] = 'car'

		bm2.load()
		self.assertRaises(KeyError, bm2.__getitem__, 'a')

		bm2.save()
		bm.update()
		bm.save()
		bm.load()
		bm2.load()

		self.assertEqual(bm['a'], bm2['a'])

if __name__ == '__main__':
	unittest.main()
hould-contain [\n" " 1 <- 97\n" // 'a' " 2 <- 1\n" " 3 <- 98\n" // 'b' " 4 <- 1\n" " 5 <- 99\n" // 'c' " 6 <- 1\n" " 7 <- 0\n" // unset " 8 <- 1\n" " 9 <- 1\n" // end of test events " ]\n" "]\n" ); } :(before "End Scenario Globals") extern const int CONSOLE = next_predefined_global_for_scenarios(/*size_of(address:console)*/2); //: give 'console' a fixed location in scenarios :(before "End Special Scenario Variable Names(r)") Name[r]["console"] = CONSOLE; //: make 'console' always a raw location in scenarios :(before "End is_special_name Special-cases") if (s == "console") return true; :(before "End Primitive Recipe Declarations") ASSUME_CONSOLE, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "assume-console", ASSUME_CONSOLE); :(before "End Primitive Recipe Checks") case ASSUME_CONSOLE: { break; } :(before "End Primitive Recipe Implementations") case ASSUME_CONSOLE: { // create a temporary recipe just for parsing; it won't contain valid instructions istringstream in("[" + current_instruction().ingredients.at(0).name + "]"); recipe r; slurp_body(in, r); int num_events = count_events(r); // initialize the events like in new-fake-console int size = /*length*/1 + num_events*size_of_event(); int event_data_address = allocate(size); // store length put(Memory, event_data_address+/*skip alloc id*/1, num_events); int curr_address = event_data_address + /*skip alloc id*/1 + /*skip length*/1; for (int i = 0; i < SIZE(r.steps); ++i) { const instruction& inst = r.steps.at(i); if (inst.name == "left-click") { trace(Callstack_depth+1, "mem") << "storing 'left-click' event starting at " << Current_routine->alloc << end(); put(Memory, curr_address, /*tag for 'touch-event' variant of 'event' exclusive-container*/2); put(Memory, curr_address+/*skip tag*/1+/*offset of 'type' in 'mouse-event'*/0, TB_KEY_MOUSE_LEFT); put(Memory, curr_address+/*skip tag*/1+/*offset of 'row' in 'mouse-event'*/1, to_integer(inst.ingredients.at(0).name)); put(Memory, curr_address+/*skip tag*/1+/*offset of 'column' in 'mouse-event'*/2, to_integer(inst.ingredients.at(1).name)); curr_address += size_of_event(); } else if (inst.name == "press") { trace(Callstack_depth+1, "mem") << "storing 'press' event starting at " << curr_address << end(); string key = inst.ingredients.at(0).name; if (is_integer(key)) put(Memory, curr_address+1, to_integer(key)); else if (contains_key(Key, key)) put(Memory, curr_address+1, Key[key]); else raise << "assume-console: can't press '" << key << "'\n" << end(); if (get_or_insert(Memory, curr_address+1) < 256) // these keys are in ascii put(Memory, curr_address, /*tag for 'text' variant of 'event' exclusive-container*/0); else { // distinguish from unicode put(Memory, curr_address, /*tag for 'keycode' variant of 'event' exclusive-container*/1); } curr_address += size_of_event(); } // End Event Handlers else { // keyboard input assert(inst.name == "type"); trace(Callstack_depth+1, "mem") << "storing 'type' event starting at " << curr_address << end(); const string& contents = inst.ingredients.at(0).name; const char* raw_contents = contents.c_str(); int num_keyboard_events = unicode_length(contents); int curr = 0; for (int i = 0; i < num_keyboard_events; ++i) { trace(Callstack_depth+1, "mem") << "storing 'text' tag at " << curr_address << end(); put(Memory, curr_address, /*tag for 'text' variant of 'event' exclusive-container*/0); uint32_t curr_character; assert(curr < SIZE(contents)); tb_utf8_char_to_unicode(&curr_character, &raw_contents[curr]); trace(Callstack_depth+1, "mem") << "storing character " << curr_character << " at " << curr_address+/*skip exclusive container tag*/1 << end(); put(Memory, curr_address+/*skip exclusive container tag*/1, curr_character); curr += tb_utf8_char_length(raw_contents[curr]); curr_address += size_of_event(); } } } assert(curr_address == event_data_address+/*skip alloc id*/1+size); // wrap the array of events in a console object int console_address = allocate(size_of_console()); trace(Callstack_depth+1, "mem") << "storing console in " << console_address << end(); put(Memory, CONSOLE+/*skip alloc id*/1, console_address); trace(Callstack_depth+1, "mem") << "storing console data in " << console_address+/*offset of 'data' in container 'events'*/1 << end(); put(Memory, console_address+/*skip alloc id*/1+/*offset of 'data' in container 'events'*/1+/*skip alloc id of 'data'*/1, event_data_address); break; } :(before "End Globals") map<string, int> Key; :(before "End One-time Setup") initialize_key_names(); :(code) void initialize_key_names() { Key["F1"] = TB_KEY_F1; Key["F2"] = TB_KEY_F2; Key["F3"] = TB_KEY_F3; Key["F4"] = TB_KEY_F4; Key["F5"] = TB_KEY_F5; Key["F6"] = TB_KEY_F6; Key["F7"] = TB_KEY_F7; Key["F8"] = TB_KEY_F8; Key["F9"] = TB_KEY_F9; Key["F10"] = TB_KEY_F10; Key["F11"] = TB_KEY_F11; Key["F12"] = TB_KEY_F12; Key["insert"] = TB_KEY_INSERT; Key["delete"] = TB_KEY_DELETE; Key["home"] = TB_KEY_HOME; Key["end"] = TB_KEY_END; Key["page-up"] = TB_KEY_PGUP; Key["page-down"] = TB_KEY_PGDN; Key["up-arrow"] = TB_KEY_ARROW_UP; Key["down-arrow"] = TB_KEY_ARROW_DOWN; Key["left-arrow"] = TB_KEY_ARROW_LEFT; Key["right-arrow"] = TB_KEY_ARROW_RIGHT; Key["ctrl-a"] = TB_KEY_CTRL_A; Key["ctrl-b"] = TB_KEY_CTRL_B; Key["ctrl-c"] = TB_KEY_CTRL_C; Key["ctrl-d"] = TB_KEY_CTRL_D; Key["ctrl-e"] = TB_KEY_CTRL_E; Key["ctrl-f"] = TB_KEY_CTRL_F; Key["ctrl-g"] = TB_KEY_CTRL_G; Key["backspace"] = TB_KEY_BACKSPACE; Key["ctrl-h"] = TB_KEY_CTRL_H; Key["tab"] = TB_KEY_TAB; Key["ctrl-i"] = TB_KEY_CTRL_I; Key["ctrl-j"] = TB_KEY_CTRL_J; Key["enter"] = TB_KEY_NEWLINE; // ignore CR/LF distinction; there is only 'enter' Key["ctrl-k"] = TB_KEY_CTRL_K; Key["ctrl-l"] = TB_KEY_CTRL_L; Key["ctrl-m"] = TB_KEY_CTRL_M; Key["ctrl-n"] = TB_KEY_CTRL_N; Key["ctrl-o"] = TB_KEY_CTRL_O; Key["ctrl-p"] = TB_KEY_CTRL_P; Key["ctrl-q"] = TB_KEY_CTRL_Q; Key["ctrl-r"] = TB_KEY_CTRL_R; Key["ctrl-s"] = TB_KEY_CTRL_S; Key["ctrl-t"] = TB_KEY_CTRL_T; Key["ctrl-u"] = TB_KEY_CTRL_U; Key["ctrl-v"] = TB_KEY_CTRL_V; Key["ctrl-w"] = TB_KEY_CTRL_W; Key["ctrl-x"] = TB_KEY_CTRL_X; Key["ctrl-y"] = TB_KEY_CTRL_Y; Key["ctrl-z"] = TB_KEY_CTRL_Z; Key["escape"] = TB_KEY_ESC; Key["ctrl-slash"] = TB_KEY_CTRL_SLASH; } :(after "Begin check_or_set_invalid_types(r)") if (is_scenario(caller)) initialize_special_name(r); :(code) bool is_scenario(const recipe& caller) { return starts_with(caller.name, "scenario_"); } void initialize_special_name(reagent& r) { if (r.type) return; // no need for screen if (r.name == "console") r.type = new_type_tree("address:console"); // End Initialize Type Of Special Name In Scenario(r) } void test_events_in_scenario() { run_mu_scenario( "scenario events-in-scenario [\n" " assume-console [\n" " type [abc]\n" " left-click 0, 1\n" " press up-arrow\n" " type [d]\n" " ]\n" " run [\n" // 3 keyboard events; each event occupies 4 locations " 1:event <- read-event console\n" " 5:event <- read-event console\n" " 9:event <- read-event console\n" // mouse click " 13:event <- read-event console\n" // non-character keycode " 17:event <- read-event console\n" // final keyboard event " 21:event <- read-event console\n" " ]\n" " memory-should-contain [\n" " 1 <- 0\n" // 'text' " 2 <- 97\n" // 'a' " 3 <- 0\n" // unused " 4 <- 0\n" // unused " 5 <- 0\n" // 'text' " 6 <- 98\n" // 'b' " 7 <- 0\n" // unused " 8 <- 0\n" // unused " 9 <- 0\n" // 'text' " 10 <- 99\n" // 'c' " 11 <- 0\n" // unused " 12 <- 0\n" // unused " 13 <- 2\n" // 'mouse' " 14 <- 65513\n" // mouse click " 15 <- 0\n" // row " 16 <- 1\n" // column " 17 <- 1\n" // 'keycode' " 18 <- 65517\n" // up arrow " 19 <- 0\n" // unused " 20 <- 0\n" // unused " 21 <- 0\n" // 'text' " 22 <- 100\n" // 'd' " 23 <- 0\n" // unused " 24 <- 0\n" // unused " 25 <- 0\n" " ]\n" "]\n" ); } //: Deal with special keys and unmatched brackets by allowing each test to //: independently choose the unicode symbol to denote them. :(before "End Primitive Recipe Declarations") REPLACE_IN_CONSOLE, :(before "End Primitive Recipe Numbers") put(Recipe_ordinal, "replace-in-console", REPLACE_IN_CONSOLE); :(before "End Primitive Recipe Checks") case REPLACE_IN_CONSOLE: { break; } :(before "End Primitive Recipe Implementations") case REPLACE_IN_CONSOLE: { assert(scalar(ingredients.at(0))); if (!get_or_insert(Memory, CONSOLE)) { raise << "console not initialized\n" << end(); break; } int console_address = get_or_insert(Memory, CONSOLE); int console_data = get_or_insert(Memory, console_address+1); int length = get_or_insert(Memory, console_data); // array length for (int i = 0, curr = console_data+1; i < length; ++i, curr+=size_of_event()) { if (get_or_insert(Memory, curr) != /*text*/0) continue; if (get_or_insert(Memory, curr+1) != ingredients.at(0).at(0)) continue; for (int n = 0; n < size_of_event(); ++n) put(Memory, curr+n, ingredients.at(1).at(n)); } break; } :(code) int count_events(const recipe& r) { int result = 0; for (int i = 0; i < SIZE(r.steps); ++i) { const instruction& curr = r.steps.at(i); if (curr.name == "type") result += unicode_length(curr.ingredients.at(0).name); else ++result; } return result; } int size_of_event() { // memoize result if already computed static int result = 0; if (result) return result; type_tree* type = new type_tree("event"); result = size_of(type); delete type; return result; } int size_of_console() { // memoize result if already computed static int result = 0; if (result) return result; assert(get(Type_ordinal, "console")); type_tree* type = new type_tree("console"); result = size_of(type); delete type; return result; }