index: Update the index design

I updated the design and rewrote the unit tests.  This creates something
more consistent with how I ended up using the index.

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2014-03-12 20:23:34 -04:00 committed by Anna Schumaker
parent fc8dc9d55e
commit 1b34a9a8a0
18 changed files with 369 additions and 414 deletions

60
DESIGN
View File

@ -203,7 +203,7 @@ Database Entry:
DatabaseEntry();
virtual void ~DatabaseEntry() = 0;
virtual std::string primary_key() = 0;
virtual const std::string primary_key() = 0;
virtual void write(File &) = 0;
virtual void read(File &) = 0;
@ -213,7 +213,7 @@ Database Entry:
DatabaseEntry :: DatabaseEntry():
Set valid = false.
std::string DatabaseEntry :: primary_key();
const std::string DatabaseEntry :: primary_key();
This function should return a unique string representing this
DatabaseEntry instance, which will be used to prevent
duplicates in a database. This string is not expected to
@ -261,7 +261,7 @@ Database:
class Database {
private:
std::vector<T> _db;
std::map<std::string, unsigned int> _keys;
std::map<const std::string, unsigned int> _keys;
unsigned int _size; /* Number of valid rows */
bool _autosave;
File _file;
@ -357,22 +357,70 @@ Database:
Index:
An index is a special database used to map a std::string key to
multiple integer values.
- IndexEntry:
class IndexEntry : public DatabaseEntry {
public:
const std::string key;
set<unsigned int> values;
IndexEntry(const std::string &);
const std::string primary_key();
void insert(unsigned int);
void remove(unsigned int);
void write(File &);
void read(File &);
void print();
void insert(unsigned int);
void remove(unsigned int);
};
File << key << endl;
File << values.size() << values[0] << .. << values[N] << endl;
- IndexEntry API:
IndexEntry :: IndexEntry();
Creat an empty IndexEntry.
std::string IndexEntry :: primary_key();
return key;
void IndexEntry :: insert(unsigned int value);
Add value to the values set.
void IndexEntry :: remove(unsigned int value);
Remove value from the values set.
void IndexEntry :: write(File &f);
Write the values set to a file.
void IndexEntry :: read(File &f);
Read values from a file.
- Index:
class Index : public Database<IndexEntry> {
public:
Index(const std::string &, bool);
void insert(const std::string &, unsigned int);
void remove(const std::string &, unsigned int);
};
- Index API:
Index :: Index(const std::string &filepath, bool autosave);
Pass values on to the Database constructor.
void Index :: insert(const std::string &key, unsigned int value);
Create an IndexEntry for key if one does not exist yet.
Insert value into the IndexEntry corresponding to key.
If autosave is enabled, save().
void Index :: remove(const std::string &key, unsigned int value);
Remove value from the IndexEntry corresponding to key. Do not
remove the IndexEntry, even if it is empty.
If autosave is enabled, save().
Filter: (lib/filter.cpp)

View File

@ -8,7 +8,6 @@
#include <print.h>
#include <map>
#include <set>
#include <vector>
@ -17,30 +16,12 @@ public:
bool valid;
DatabaseEntry();
virtual std::string primary_key() = 0;
virtual const std::string primary_key() = 0;
virtual void write(File &) = 0;
virtual void read(File &) = 0;
};
class IndexEntry : public DatabaseEntry {
public:
std::string key;
std::set<unsigned int> values;
IndexEntry();
IndexEntry(const std::string &, unsigned int);
~IndexEntry();
std::string primary_key();
void write(File &);
void read(File &);
#ifdef CONFIG_TEST
void print();
#endif /* CONFIG_TEST */
void insert(unsigned int);
void remove(unsigned int);
};
template <class T>
class Database {
@ -51,8 +32,6 @@ private:
bool _autosave;
File _file;
void autosave();
public:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
@ -60,6 +39,7 @@ public:
Database(std::string, bool);
~Database();
void save();
void autosave();
void load();
unsigned int insert(T);
@ -75,29 +55,6 @@ public:
iterator find(const std::string &);
};
static inline void index_insert(Database<IndexEntry> &db,
const std::string &key,
unsigned int val)
{
Database<IndexEntry>::iterator it = db.find(key);
if (it == db.end()) {
db.insert(IndexEntry(key, val));
} else
it->insert(val);
}
static inline void index_remove(Database<IndexEntry> &db,
const std::string &key,
unsigned int val)
{
Database<IndexEntry>::iterator it = db.find(key);
if (it != db.end()) {
it->remove(val);
if (it->values.size() == 0)
db.remove(it - db.begin());
}
}
#include "database.hpp"
#endif /* OCARINA_DATABASE_H */

View File

@ -4,7 +4,7 @@
#ifndef OCARINA_FILTER_H
#define OCARINA_FILTER_H
#include <database.h>
#include <set>
#include <string>
namespace filter {
@ -15,10 +15,6 @@ namespace filter {
void print_cache_stats();
#ifdef CONFIG_TEST
Database<IndexEntry> &get_index();
#endif /* CONFIG_TEST */
};
#endif /* OCARINA_FILTER_H */

38
include/index.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#ifndef OCARINA_INDEX_H
#define OCARINA_INDEX_H
#include <database.h>
#include <set>
#include <string>
class IndexEntry : public DatabaseEntry {
public:
std::string key;
std::set<unsigned int> values;
IndexEntry();
IndexEntry(const std::string &);
const std::string primary_key();
void insert(unsigned int);
void remove(unsigned int);
void write(File &);
void read(File &);
};
class Index : public Database<IndexEntry> {
public:
Index(const std::string &, bool);
void insert(const std::string &, unsigned int);
void remove(const std::string &, unsigned int);
};
#endif /* OCARINA_DATABASE_H */

View File

@ -33,7 +33,7 @@ namespace library
AGInfo();
AGInfo(DB_Type, TagLib :: Tag *);
AGInfo(DB_Type, const std::string &);
std::string primary_key();
const std::string primary_key();
void read(File &);
void write(File &);
};
@ -49,7 +49,7 @@ namespace library
Album();
Album(TagLib :: Tag *, unsigned int);
Album(const std::string &, unsigned int, unsigned int);
std::string primary_key();
const std::string primary_key();
void read(File &);
void write(File &);
};
@ -63,7 +63,7 @@ namespace library
Library();
Library(const std::string &, bool);
std::string primary_key();
const std::string primary_key();
void read(File &);
void write(File &);
};
@ -95,7 +95,7 @@ namespace library
unsigned int, const std :: string &);
Track(ImportData *, unsigned int, unsigned int,
unsigned int, unsigned int);
std::string primary_key();
const std::string primary_key();
void read(File &);
void write(File &);
};

View File

@ -8,67 +8,3 @@ DatabaseEntry :: DatabaseEntry()
: valid(false)
{
}
IndexEntry :: IndexEntry()
{
}
IndexEntry :: IndexEntry(const std::string &k, unsigned int v)
{
key = k;
insert(v);
}
IndexEntry :: ~IndexEntry()
{
}
std::string IndexEntry :: primary_key()
{
return key;
}
void IndexEntry :: write(File &f)
{
std::set<unsigned int>::iterator it;
f << key << std::endl << values.size() << " ";
for (it = values.begin(); it != values.end(); it++)
f << *it << " ";
}
void IndexEntry :: read(File &f)
{
unsigned int num, val;
f >> key >> num;
for (unsigned int i = 0; i < num; i++) {
f >> val;
values.insert(val);
}
}
#ifdef CONFIG_TEST
void IndexEntry :: print()
{
std::set<unsigned int>::iterator it;
:: print("{");
for (it = values.begin(); it != values.end(); it++) {
if (it != values.begin())
:: print(" ");
:: print("%d", *it);
}
:: print("}");
}
#endif /* CONFIG_TEST */
void IndexEntry :: insert(unsigned int val)
{
values.insert(val);
}
void IndexEntry :: remove(unsigned int val)
{
values.erase(val);
}

View File

@ -3,14 +3,14 @@
*/
#include <filter.h>
#include <index.h>
#include <print.h>
#include <algorithm>
#include <list>
#include <map>
#include <set>
static Database<IndexEntry> filter_index("", false);
static Index filter_index("", false);
static std::map<std::string, std::string> lowercase_cache;
static unsigned int lowercase_cache_hits = 0;
@ -91,7 +91,7 @@ static void add_substrings(const std::string &text, unsigned int track_id)
std::string substr;
for (unsigned int i = 1; i <= text.size(); i++) {
substr = text.substr(0, i);
index_insert(filter_index, substr, track_id);
filter_index.insert(substr, track_id);
}
}
@ -107,7 +107,7 @@ void filter :: add(const std::string &text, unsigned int track_id)
static void find_intersection(std::string &text, std::set<unsigned int> &res)
{
Database<IndexEntry>::iterator it = filter_index.find(text);
Index::iterator it = filter_index.find(text);
std::set<unsigned int> tmp;
set_intersection(it->values.begin(), it->values.end(),
@ -157,10 +157,3 @@ void filter :: print_cache_stats()
print("Lowercase cache size: %u\n", lowercase_cache.size());
print("Lowercase cache hits: %u\n", lowercase_cache_hits);
}
#ifdef CONFIG_TEST
Database<IndexEntry> &filter :: get_index()
{
return filter_index;
}
#endif /* CONFIG_TEST */

71
lib/index.cpp Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright 2014 (c) Anna Schumaker.
*/
#include <index.h>
IndexEntry :: IndexEntry() {}
IndexEntry :: IndexEntry(const std::string &k)
: key(k)
{}
const std::string IndexEntry :: primary_key()
{
return key;
}
void IndexEntry :: insert(unsigned int val)
{
values.insert(val);
}
void IndexEntry :: remove(unsigned int val)
{
values.erase(val);
}
void IndexEntry :: write(File &f)
{
std::set<unsigned int>::iterator it;
f << key << std::endl << values.size() << " ";
for (it = values.begin(); it != values.end(); it++)
f << *it << " ";
}
void IndexEntry :: read(File &f)
{
unsigned int num, val;
f >> key >> num;
for (unsigned int i = 0; i < num; i++) {
f >> val;
insert(val);
}
}
Index :: Index(const std::string &filepath, bool autosave)
: Database(filepath, autosave)
{}
void Index :: insert(const std::string &key, unsigned int val)
{
iterator it = find(key);
if (it == end())
it = at(Database :: insert(IndexEntry(key)));
it->insert(val);
autosave();
}
void Index :: remove(const std::string &key, unsigned int val)
{
iterator it = find(key);
if (it == end())
return;
it->remove(val);
autosave();
}

View File

@ -60,7 +60,7 @@ library :: AGInfo :: AGInfo(DB_Type type, const std::string &str)
throw -E_INVAL;
}
std::string library :: AGInfo :: primary_key()
const std::string library :: AGInfo :: primary_key()
{
return name;
}
@ -100,7 +100,7 @@ library :: Album :: Album(const std::string &str, unsigned int yr, unsigned int
name_lower = filter :: to_lowercase(name);
}
std::string library :: Album :: primary_key()
const std::string library :: Album :: primary_key()
{
std::stringstream ss;
ss << artist_id << "." << name << "." << year;
@ -135,7 +135,7 @@ library :: Library :: Library(const std::string &path, bool is_enabled)
{
}
std::string library :: Library :: primary_key()
const std::string library :: Library :: primary_key()
{
return root_path;
}
@ -211,7 +211,7 @@ library :: Track :: Track(struct ImportData *data, unsigned int lib,
length_str = ss.str();
}
std::string library :: Track :: primary_key()
const std::string library :: Track :: primary_key()
{
return full_path;
}

View File

@ -2,12 +2,12 @@
* Copyright 2013 (c) Anna Schumaker.
*/
#include <callback.h>
#include <database.h>
#include <error.h>
#include <index.h>
#include <playlist.h>
static std::set<unsigned int> empty_set;
static Database<IndexEntry> playlist_db("playlist.db", false);
static Index playlist_db("playlist.db", false);
static Playqueue playlist_pq(PQ_ENABLED);
static std::string cur_pq;
@ -46,7 +46,7 @@ void playlist :: init()
void playlist :: add(const std::string &name, unsigned int track_id)
{
if ((name == "Banned") || (name == "Favorites")) {
index_insert(playlist_db, name, track_id);
playlist_db.insert(name, track_id);
playlist_db.save();
if (name == cur_pq)
playlist_pq.add(track_id);
@ -59,7 +59,7 @@ void playlist :: add(const std::string &name, unsigned int track_id)
void playlist :: del(const std::string &name, unsigned int track_id)
{
if ((name == "Banned") || (name == "Favorites")) {
index_remove(playlist_db, name, track_id);
playlist_db.remove(name, track_id);
playlist_db.save();
if (name == cur_pq)
playlist_pq.del_track(track_id);

View File

@ -8,9 +8,8 @@ if sys.argv.count("tests") > 0:
src = SConscript("src/Sconscript")
tests = [ "version", "file", "db_entry", "database" ]
#scripts = [ "print", "file", "database", "index", "filter", "idle", "playlist",
# "library", "playqueue", "deck", "audio", "gui" ]
tests = [ "version", "file", "db_entry", "database", "index" ]
#scripts = [ "filter", "idle", "playlist", "library", "playqueue", "deck", "audio", "gui" ]
prev = None

45
tests/index Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
# Copyright 2014 (c) Anna Schumaker
. $(dirname $0)/_functions
function test_autosave
{
new_test "Index Test (n = $1, autosave = true)"
src/index.run -a $1
if [ ! -f $DATA_DIR/index.idx ]; then
echo "ERROR: $DATA_DIR/index.db doesn't exist!"
exit 1
fi
}
function test_noautosave
{
new_test "Index Test (n = $1, autosave = false)"
src/index.run $1
if [ -f $DATA_DIR/index.idx ]; then
echo "ERROR: $DATA_DIR/index.idx exists!"
exit 1
fi
}
function run_test
{
rm $DATA_DIR/* 2>/dev/null || true
if [ $1 -lt 1000 ]; then
test_autosave $1
else
test_noautosave $1
fi
}
run_test 10
echo
run_test 100
echo
run_test 1000
echo
run_test 10000
echo
run_test 100000

View File

@ -1,6 +0,0 @@
#!/usr/bin/python
Import("Test", "CONFIG")
CONFIG.DATABASE = True
Test("index", "index.cpp")

View File

@ -1,152 +0,0 @@
/*
* Copyright 2013 (c) Anna Schumaker.
*/
#include <database.h>
#include <print.h>
void print_index(Database<IndexEntry> &index)
{
std::set<std::string>::iterator s_it;
std::set<unsigned int>::iterator u_it;
print("=== Printing index ===\n");
index.print_keys();
for (unsigned int i = index.first(); i != index.num_rows(); i = index.next(i)) {
print("index[%s] = ", index[i].primary_key.c_str());
index[i].print();
print("\n");
}
print("\n");
}
void populate_index(Database<IndexEntry> &index)
{
std::string key_str;
for (char key = 'a'; key <= 'z'; key++) {
key_str = key;
for (unsigned int value = 0; value < 10; value++)
index_insert(index, key_str, value);
}
}
void remove_keys(Database<IndexEntry> &index)
{
std::string key_str;
for (char key = 'a'; key <= 'z'; key+=2) {
key_str = key;
index.remove(index.find_index(key_str));
if (index.has_key(key_str))
print("Failed to remove key!\n");
}
}
void remove_values(Database<IndexEntry> &index)
{
std::string key_str;
unsigned int limit = 0;
for (char key = 'a'; key <= 'z'; key++) {
key_str = key;
for (unsigned int i = 0; i < limit; i++)
index_remove(index, key_str, i);
limit++;
if (limit == 11) {
limit = 0;
if (index.has_key(key_str))
print("Failed to remove key!\n");
}
}
}
/*
* Test index creation, print key access
*/
void test_0()
{
print("Test 0\n");
Database<IndexEntry> index("");
populate_index(index);
print_index(index);
}
/*
* Test removing keys from an index
*/
void test_1()
{
print("Test 1\n");
Database<IndexEntry> index("");
populate_index(index);
remove_keys(index);
print_index(index);
}
/*
* Test removing values from an index
*/
void test_2()
{
print("Test 2\n");
Database<IndexEntry> index("");
populate_index(index);
remove_values(index);
print_index(index);
}
/*
* Save the database to disk
*/
void test_3()
{
print("Test 3\n");
Database<IndexEntry> index("test.idx");
populate_index(index);
remove_values(index);
index.save();
}
/*
* Reload the database from disk
*/
void test_4()
{
print("Test 4\n");
Database<IndexEntry> index("test.idx");
index.load();
print_index(index);
}
/*
* Test access to keys that don't exist
*/
void test_5()
{
print("Test 5\n");
Database<IndexEntry> index("");
print("index[nokey].size() = ");
try {
print("%u\n", index.find("nokey").values.size());
} catch (...) {
print("0\n");
}
}
int main(int argc, char **argv)
{
test_0();
test_1();
test_2();
test_3();
test_4();
test_5();
return 0;
}

View File

@ -1,106 +0,0 @@
Test 0
=== Printing index ===
Found keys: a b c d e f g h i j k l m n o p q r s t u v w x y z
index[a] = {0 1 2 3 4 5 6 7 8 9}
index[b] = {0 1 2 3 4 5 6 7 8 9}
index[c] = {0 1 2 3 4 5 6 7 8 9}
index[d] = {0 1 2 3 4 5 6 7 8 9}
index[e] = {0 1 2 3 4 5 6 7 8 9}
index[f] = {0 1 2 3 4 5 6 7 8 9}
index[g] = {0 1 2 3 4 5 6 7 8 9}
index[h] = {0 1 2 3 4 5 6 7 8 9}
index[i] = {0 1 2 3 4 5 6 7 8 9}
index[j] = {0 1 2 3 4 5 6 7 8 9}
index[k] = {0 1 2 3 4 5 6 7 8 9}
index[l] = {0 1 2 3 4 5 6 7 8 9}
index[m] = {0 1 2 3 4 5 6 7 8 9}
index[n] = {0 1 2 3 4 5 6 7 8 9}
index[o] = {0 1 2 3 4 5 6 7 8 9}
index[p] = {0 1 2 3 4 5 6 7 8 9}
index[q] = {0 1 2 3 4 5 6 7 8 9}
index[r] = {0 1 2 3 4 5 6 7 8 9}
index[s] = {0 1 2 3 4 5 6 7 8 9}
index[t] = {0 1 2 3 4 5 6 7 8 9}
index[u] = {0 1 2 3 4 5 6 7 8 9}
index[v] = {0 1 2 3 4 5 6 7 8 9}
index[w] = {0 1 2 3 4 5 6 7 8 9}
index[x] = {0 1 2 3 4 5 6 7 8 9}
index[y] = {0 1 2 3 4 5 6 7 8 9}
index[z] = {0 1 2 3 4 5 6 7 8 9}
Test 1
=== Printing index ===
Found keys: b d f h j l n p r t v x z
index[b] = {0 1 2 3 4 5 6 7 8 9}
index[d] = {0 1 2 3 4 5 6 7 8 9}
index[f] = {0 1 2 3 4 5 6 7 8 9}
index[h] = {0 1 2 3 4 5 6 7 8 9}
index[j] = {0 1 2 3 4 5 6 7 8 9}
index[l] = {0 1 2 3 4 5 6 7 8 9}
index[n] = {0 1 2 3 4 5 6 7 8 9}
index[p] = {0 1 2 3 4 5 6 7 8 9}
index[r] = {0 1 2 3 4 5 6 7 8 9}
index[t] = {0 1 2 3 4 5 6 7 8 9}
index[v] = {0 1 2 3 4 5 6 7 8 9}
index[x] = {0 1 2 3 4 5 6 7 8 9}
index[z] = {0 1 2 3 4 5 6 7 8 9}
Test 2
=== Printing index ===
Found keys: a b c d e f g h i j l m n o p q r s t u w x y z
index[a] = {0 1 2 3 4 5 6 7 8 9}
index[b] = {1 2 3 4 5 6 7 8 9}
index[c] = {2 3 4 5 6 7 8 9}
index[d] = {3 4 5 6 7 8 9}
index[e] = {4 5 6 7 8 9}
index[f] = {5 6 7 8 9}
index[g] = {6 7 8 9}
index[h] = {7 8 9}
index[i] = {8 9}
index[j] = {9}
index[l] = {0 1 2 3 4 5 6 7 8 9}
index[m] = {1 2 3 4 5 6 7 8 9}
index[n] = {2 3 4 5 6 7 8 9}
index[o] = {3 4 5 6 7 8 9}
index[p] = {4 5 6 7 8 9}
index[q] = {5 6 7 8 9}
index[r] = {6 7 8 9}
index[s] = {7 8 9}
index[t] = {8 9}
index[u] = {9}
index[w] = {0 1 2 3 4 5 6 7 8 9}
index[x] = {1 2 3 4 5 6 7 8 9}
index[y] = {2 3 4 5 6 7 8 9}
index[z] = {3 4 5 6 7 8 9}
Test 3
Test 4
=== Printing index ===
Found keys: a b c d e f g h i j l m n o p q r s t u w x y z
index[a] = {0 1 2 3 4 5 6 7 8 9}
index[b] = {1 2 3 4 5 6 7 8 9}
index[c] = {2 3 4 5 6 7 8 9}
index[d] = {3 4 5 6 7 8 9}
index[e] = {4 5 6 7 8 9}
index[f] = {5 6 7 8 9}
index[g] = {6 7 8 9}
index[h] = {7 8 9}
index[i] = {8 9}
index[j] = {9}
index[l] = {0 1 2 3 4 5 6 7 8 9}
index[m] = {1 2 3 4 5 6 7 8 9}
index[n] = {2 3 4 5 6 7 8 9}
index[o] = {3 4 5 6 7 8 9}
index[p] = {4 5 6 7 8 9}
index[q] = {5 6 7 8 9}
index[r] = {6 7 8 9}
index[s] = {7 8 9}
index[t] = {8 9}
index[u] = {9}
index[w] = {0 1 2 3 4 5 6 7 8 9}
index[x] = {1 2 3 4 5 6 7 8 9}
index[y] = {2 3 4 5 6 7 8 9}
index[z] = {3 4 5 6 7 8 9}
Test 5
index[nokey].size() = 0

View File

@ -20,7 +20,7 @@ public:
IntEntry();
IntEntry(unsigned int);
std::string primary_key();
const std::string primary_key();
void write(File &);
void read(File &);
void print();
@ -28,7 +28,7 @@ public:
IntEntry :: IntEntry() : val(0) {}
IntEntry :: IntEntry(unsigned int v) : val(v) {}
std::string IntEntry :: primary_key()
const std::string IntEntry :: primary_key()
{
std::stringstream ss;
ss << val;

View File

@ -19,7 +19,7 @@ public:
std::string key;
IntEntry(unsigned int, const std::string &);
std::string primary_key();
const std::string primary_key();
void write(File &);
void read(File &);
void print();
@ -31,7 +31,7 @@ IntEntry :: IntEntry(unsigned int i, const std::string &s)
key = s;
}
std::string IntEntry :: primary_key()
const std::string IntEntry :: primary_key()
{
return key;
}

136
tests/src/index.cpp Normal file
View File

@ -0,0 +1,136 @@
/*
* Copyright 2014 (c) Anna Schumaker.
* Test a Database
*/
#include <index.h>
#include <print.h>
#include <stdlib.h>
#include <unistd.h>
unsigned int test_num = 0;
void test_results(bool success, unsigned int line)
{
print(" %u: ", test_num);
if (success)
print("Success!\n");
else {
print("FAILED (%u) =(\n", line);
exit(1);
}
test_num++;
}
int main(int argc, char **argv)
{
bool autosave = false;
unsigned int n;
char c;
while ((c = getopt(argc, argv, "a")) != -1) {
switch (c) {
case 'a':
autosave = true;
break;
}
}
n = atoi(argv[optind]);
Index index("index.idx", autosave);
/**
* 0: Test inserting when there is no key
*/
index.insert("a", 0);
Index :: iterator it = index.find("a");
if (it == index.end())
test_results(false, __LINE__);
if (it->values.size() == 0)
test_results(false, __LINE__);
test_results(*(it->values.begin()) == 0, __LINE__);
/**
* 1: Test removing
*/
index.remove("a", 0);
test_results((index.size() == 1) && (index.find("a")->values.size() == 0), __LINE__);
/**
* 2: Test adding multiple values
*/
for (c = 'a'; c <= 'z'; c++) {
std::string key = "";
key += c;
for (unsigned int i = 0; i < n; i++)
index.insert(key, i);
}
test_results(index.size() == 26, __LINE__);
/**
* 3: Make sure we have multiple values for each key
*/
for (c = 'a'; c <= 'z'; c++) {
std::string key = "";
key += c;
if (index.find(key)->values.size() != n)
test_results(false, __LINE__);
}
test_results(true, __LINE__);
/**
* 4: Test removing multiple values
*/
for (c = 'a'; c <= 'z'; c+=2) {
std::string key = "";
key += c;
for (unsigned int i = 0; i < n; i++)
index.remove(key, i);
if (index.find(key)->values.size() > 0)
test_results(false, __LINE__);
}
test_results(index.size() == 26, __LINE__);
/**
* Everything after this point tests loading from a file
*/
if (autosave == false)
return 0;
Index index2("index.idx", autosave);
index2.load();
/**
* 5: Load database from file
*/
test_results(index.size() == index2.size(), __LINE__);
/**
* 6: Check that everything is the right size
*/
for (c = 'a'; c <= 'z'; c++) {
std::string key = "";
key += c;
if (index.find(key)->values.size() != index2.find(key)->values.size())
test_results(false, __LINE__);
}
test_results(true, __LINE__);
return 0;
}