1/*
2 * Copyright 2019 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * 		Simon South, simon@simonsouth.net
7 */
8
9
10#include <stdio.h>
11#include <string.h>
12
13#include <map>
14
15#include <cppunit/TestCaller.h>
16#include <cppunit/TestSuite.h>
17
18#include "KeymapTest.h"
19
20
21KeymapTest::KeymapTest()
22{
23	fCurrentKeymap.SetToCurrent();
24	fDefaultKeymap.SetToDefault();
25}
26
27
28KeymapTest::~KeymapTest()
29{
30}
31
32
33void
34KeymapTest::TestEquals()
35{
36	CPPUNIT_ASSERT(fCurrentKeymap == fCurrentKeymap);
37	CPPUNIT_ASSERT(fDefaultKeymap == fDefaultKeymap);
38
39	BKeymap keymap;
40
41	keymap.SetToCurrent();
42	CPPUNIT_ASSERT(keymap == fCurrentKeymap);
43
44	keymap.SetToDefault();
45	CPPUNIT_ASSERT(keymap == fDefaultKeymap);
46}
47
48
49void
50KeymapTest::TestAssignment()
51{
52	BKeymap keymap;
53
54	keymap = fCurrentKeymap;
55	CPPUNIT_ASSERT(keymap == fCurrentKeymap);
56
57	keymap = fDefaultKeymap;
58	CPPUNIT_ASSERT(keymap == fDefaultKeymap);
59}
60
61
62void
63KeymapTest::TestGetChars()
64{
65	// Get a copy of the currently loaded keymap
66	key_map* keymap;
67	char* charArray;
68
69	get_key_map(&keymap, &charArray);
70	CPPUNIT_ASSERT(keymap != NULL);
71
72	// Test each of the keymap's character tables
73	typedef std::map<uint32, int32(*)[128]> table_map_t;
74	table_map_t tables;
75	tables[0] = &keymap->normal_map;
76	tables[B_SHIFT_KEY] = &keymap->shift_map;
77	tables[B_CAPS_LOCK] = &keymap->caps_map;
78	tables[B_CAPS_LOCK | B_SHIFT_KEY] = &keymap->caps_shift_map;
79	tables[B_CONTROL_KEY] = &keymap->control_map;
80	tables[B_OPTION_KEY] = &keymap->option_map;
81	tables[B_OPTION_KEY | B_SHIFT_KEY] = &keymap->option_shift_map;
82	tables[B_OPTION_KEY | B_CAPS_LOCK] = &keymap->option_caps_map;
83	tables[B_OPTION_KEY | B_SHIFT_KEY | B_CAPS_LOCK] =
84		&keymap->option_caps_shift_map;
85
86	for (table_map_t::const_iterator p = tables.begin();
87		 p != tables.end(); p++) {
88		const uint32 modifiers = (*p).first;
89		const int32(*table)[128] = (*p).second;
90
91		// Test, for every keycode, that the result from BKeymap::GetChars()
92		// matches what we find in our our own copy of the keymap
93		for (uint32 keycode = 0; keycode < 128; keycode++) {
94			char* mapChars = &charArray[(*table)[keycode]];
95
96			// If the keycode isn't mapped, try again without the Option key
97			if (*mapChars <= 0 && (modifiers & B_OPTION_KEY) != 0) {
98				int newOffset = (*tables[modifiers & ~B_OPTION_KEY])[keycode];
99				if (newOffset >= 0)
100					mapChars = &charArray[newOffset];
101			}
102
103			char* chars;
104			int32 numBytes;
105			fCurrentKeymap.GetChars(keycode, modifiers, 0, &chars, &numBytes);
106
107			CPPUNIT_ASSERT(*mapChars <= 0 || chars != NULL);
108			CPPUNIT_ASSERT_EQUAL(*mapChars, numBytes);
109			CPPUNIT_ASSERT(strncmp(chars, mapChars + 1, numBytes) == 0);
110		}
111	}
112
113	delete keymap;
114	delete[] charArray;
115}
116
117
118/* static */ void
119KeymapTest::AddTests(BTestSuite& parent)
120{
121	CppUnit::TestSuite& suite = *new CppUnit::TestSuite("KeymapTest");
122
123	suite.addTest(new CppUnit::TestCaller<KeymapTest>(
124		"KeymapTest::TestEquals", &KeymapTest::TestEquals));
125	suite.addTest(new CppUnit::TestCaller<KeymapTest>(
126		"KeymapTest::TestAssignment", &KeymapTest::TestAssignment));
127	suite.addTest(new CppUnit::TestCaller<KeymapTest>(
128		"KeymapTest::TestGetChars", &KeymapTest::TestGetChars));
129
130	parent.addTest("KeymapTest", &suite);
131}
132