All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ohmdb.test.TestCommons Maven / Gradle / Ivy

package com.ohmdb.test;

/*
 * #%L
 * ohmdb-test
 * %%
 * Copyright (C) 2013 - 2014 Nikolche Mihajlovski
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;

import com.google.common.base.Objects;
import com.ohmdb.abstracts.DatastoreTransaction;
import com.ohmdb.abstracts.FutureIds;
import com.ohmdb.abstracts.Numbers;
import com.ohmdb.abstracts.RWRelation;
import com.ohmdb.abstracts.ReadOnlyRelation;
import com.ohmdb.api.Db;
import com.ohmdb.api.Links;
import com.ohmdb.api.ManyToMany;
import com.ohmdb.api.ManyToOne;
import com.ohmdb.api.Ohm;
import com.ohmdb.api.OhmDB;
import com.ohmdb.api.OneToMany;
import com.ohmdb.api.Table;
import com.ohmdb.api.Transaction;
import com.ohmdb.api.TransactionListener;
import com.ohmdb.dsl.join.DefaultJoinConfig;
import com.ohmdb.dsl.join.JoinConfig;
import com.ohmdb.dsl.join.JoinQuery;
import com.ohmdb.dsl.join.LinkMatcher;
import com.ohmdb.impl.OhmDBImpl;
import com.ohmdb.join.futureid.IDS;
import com.ohmdb.numbers.Nums;
import com.ohmdb.util.Check;
import com.ohmdb.util.Errors;
import com.ohmdb.util.U;
import com.ohmdb.util.UTILS;

public abstract class TestCommons {

	protected static final int X = 1000001;
	protected static final int Y = X + 1;
	protected static final int Z = X + 2;
	protected static final int W = X + 3;
	protected static final int Q = X + 4;

	protected static final String DB_FILE = tmpFile("ohm", ".db").getAbsolutePath();

	public static Table TBL1 = new MockTable("TBL1", Nums.arrFromTo(0, 10));

	public static Table TBL2 = new MockTable("TBL2", Nums.arrFromTo(0, 10));

	public static Table TBL3 = new MockTable("TBL3", Nums.arrFromTo(0, 10));

	protected WeakReference DB_REF;

	protected static Numbers ids0to10;

	// make non-null for debugging sync
	private static final Object THREADS_SYNC = null; // TODO must be null for
														// real testing!

	protected static final Random RND = new Random();

	private static boolean verbose = true;

	protected Transaction TX;

	protected Db db;
	protected Table persons;
	protected Table books;
	protected Table tags;

	protected ManyToMany friends;

	protected OneToMany wrote;
	protected ManyToOne writtenBy;

	protected ManyToMany follows;
	protected ManyToMany followedBy;

	protected ManyToOne describes;
	protected OneToMany describedBy;

	protected Person $p;
	protected Book $b;
	protected Tag $t;

	protected  List list(Iterator it) {
		List list = new ArrayList();

		while (it.hasNext()) {
			list.add(it.next());
		}

		return list;
	}

	protected  void isNull(Object value) {
		Assert.assertNull(value);
	}

	protected  void isntNull(Object value) {
		Assert.assertNotNull(value);
	}

	protected  void isTrue(boolean cond) {
		Assert.assertTrue(cond);
	}

	protected  void isFalse(boolean cond) {
		Assert.assertFalse(cond);
	}

	protected static  void eq(long value, long expected) {
		eq(new Long(value), new Long(expected));
	}

	protected static  void eq(T value, T expected) {
		if (!Objects.equal(value, expected)) {
			Assert.assertEquals(value, expected);
		}
	}

	protected static  void eqs(long[] values, long... expected) {
		if (verbose) {
			System.out.println("EXPECTED: " + U.text(expected));
			System.out.println(" - FOUND: " + U.text(values));
		}
		Assert.assertEquals(values.length, expected.length);

		for (int i = 0; i < expected.length; i++) {
			Assert.assertEquals(values[i], expected[i]);
		}
	}

	protected static  void eqs(Object[] values, Object... expected) {
		if (verbose) {
			System.out.println("EXPECTED: " + U.text(expected));
			System.out.println(" - FOUND: " + U.text(values));
		}
		Assert.assertEquals(values.length, expected.length);

		for (int i = 0; i < expected.length; i++) {
			Assert.assertEquals(values[i], expected[i]);
		}
	}

	protected static  void eqv(T value, T expected) {
		if (verbose) {
			System.out.println("EXPECTED: " + expected);
			System.out.println(" - FOUND: " + value);
		}
		Assert.assertEquals(value, expected);
	}

	protected  void eq(List list, T... values) {
		if (verbose) {
			System.out.println("EXPECTED: " + Arrays.toString(values));
			System.out.println(" - FOUND: " + list);
		}
		Assert.assertEquals(list.toArray(), values);
	}

	protected void eqnums(long[] numbers, long... values) {
		eq(numbers, values);
	}

	protected void eqnums(Numbers numbers, long... values) {
		detailedEqNums(numbers, values);

		detailedEqNums(Nums.unionAll(numbers), values);
		detailedEqNums(Nums.union(numbers, numbers), values);
		detailedEqNums(Nums.union(numbers, Nums.none()), values);
		detailedEqNums(Nums.unionAll(numbers, Nums.none(), numbers), values);
		detailedEqNums(Nums.intersectAll(new Numbers[] { numbers }), values);
		detailedEqNums(Nums.intersect(numbers, numbers), values);
	}

	private void detailedEqNums(Numbers numbers, long... values) {
		long[] arr = numbers.toArray();
		if (verbose) {
			System.out.println("EXPECTED: " + Arrays.toString(values));
			System.out.println(" - FOUND: " + Arrays.toString(arr));
		}
		Assert.assertEquals(arr, values);
	}

	protected void eqlinks(Links paths, long[]... fromTos) {
		eqlinks(paths, links(fromTos));
	}

	protected void eqnull(Object... values) {
		for (Object value : values) {
			Assert.assertNull(value);
		}
	}

	protected void eqlinks(Links paths, Links expected) {
		if (verbose) {
			System.out.println("EXPECTED: " + UTILS.toString(expected));
			System.out.println(" - FOUND: " + UTILS.toString(paths));
		}
		Assert.assertTrue(UTILS.equal(paths, expected));
	}

	protected void linksEQ(Links[] links, Links[] expected) {
		if (verbose) {
			System.out.println("EXPECTED: " + U.text(expected));
			System.out.println(" - FOUND: " + U.text(links));
		}
		isTrue(UTILS.equal(links, expected));
	}

	protected void neq(Links paths, Links notExpected) {
		if (verbose) {
			System.out.println("NOT EXPECTED: " + UTILS.toString(notExpected));
			System.out.println("     - FOUND: " + UTILS.toString(paths));
		}
		Assert.assertFalse(UTILS.equal(paths, notExpected));
	}

	public static void check(boolean state) {
		Assert.assertTrue(state);
	}

	public static void time(String msg) {
		System.out.println("=== " + msg + " " + new Date());
	}

	public static Iterator randomIterator(final int max, final int count) {
		return new RandomIterator(count, max);
	}

	public Numbers nums(long... numbers) {
		return Nums.from(numbers);
	}

	public static void print(Object obj) {
		System.out.println(U.text(obj));
	}

	public static void printn(Object... obj) {
		System.out.println(Arrays.toString(obj));
	}

	public static long[] ln(long... fromTo) {
		return fromTo;
	}

	public Links links(long[]... fromTos) {
		return UTILS.linksFromTos(fromTos);
	}

	public JoinConfig jparam(JoinQuery query, Numbers... ids) {
		return new DefaultJoinConfig(IDS.futureIds(ids), query.joins());
	}

	public JoinConfig jparam(JoinQuery query, FutureIds... futureIds) {
		return new DefaultJoinConfig(futureIds, query.joins());
	}

	public JoinConfig jparam0to10(JoinQuery query, Numbers... ids) {
		for (int i = 0; i < ids.length; i++) {
			if (ids[i] == null) {
				ids[i] = Nums.fromTo(0, 10);
			}
		}

		return jparam(query, ids);
	}

	public static Links ln(Links[] links) {
		Check.state(links.length == 1);
		return links[0];
	}

	public static Links[] nlinks(Links... links) {
		return links;
	}

	protected  Table table(Class clazz) {
		return db.table(clazz);
	}

	protected Table personsTable() {
		return db.table(Person.class);
	}

	protected Table booksTable() {
		return db.table(Book.class);
	}

	protected Table tagsTable() {
		return db.table(Tag.class);
	}

	protected static Person person(String name, int age) {
		return new Person(name, age);
	}

	protected static Person2 person2(String name, int age) {
		return new Person2(name, age);
	}

	protected static Book book(String title, boolean published) {
		return new Book(title, published);
	}

	protected static Tag tag(String name) {
		return new Tag(name);
	}

	@DataProvider(name = "orderProvider")
	public Object[][] orderProvider() {
		int[] order1 = { 0, 1 };
		int[] order2 = { 1, 0 };

		Object[][] data = { { order1 }, { order2 } };
		return data;
	}

	@DataProvider(name = "orderProvider2")
	public Object[][] orderProvider2() {
		int[] order1 = { 0, 1, 2 };
		int[] order2 = { 0, 2, 1 };
		int[] order3 = { 1, 0, 2 };
		int[] order4 = { 1, 2, 0 };
		int[] order5 = { 2, 1, 0 };
		int[] order6 = { 2, 0, 1 };

		Object[][] data = { { order1 }, { order2 }, { order3 }, { order4 }, { order5 }, { order6 } };
		return data;
	}

	public static void setVerbose(boolean verbose) {
		TestCommons.verbose = verbose;
	}

	protected ThreadPack threads(String name, final int threadCount, final int cyclesCount, final boolean debug,
			final Parallel parallel) {

		final ThreadPack pack = new ThreadPack(name, threadCount, cyclesCount);

		for (int i = 0; i < threadCount; i++) {
			final int n = i + 1;
			pack.threads[i] = new Thread() {
				public void run() {
					if (debug) {
						System.out.println(" - started thread " + n + " / " + threadCount);
					}

					try {
						parallel.init(n);
						for (int j = 0; j < cyclesCount; j++) {
							if (THREADS_SYNC != null) {
								synchronized (THREADS_SYNC) {
									System.out.println("THREADS SYNC IN");
									parallel.run(n, j);
									System.out.println("THREADS SYNC OUT");
								}
							} else {
								parallel.run(n, j);
							}
						}
					} catch (Throwable e) {
						pack.error(e);
					}

					if (debug) {
						System.out.println(" - finished thread " + n + " / " + threadCount);
					}

					pack.done(parallel);
				}
			};
		}

		return pack;
	}

	protected ThreadPack threads(String name, final int threadCount, final int cyclesCount, final boolean debug,
			final Class parallelClass, final Object[] args) {

		final ThreadPack pack = new ThreadPack(name, threadCount, cyclesCount);

		for (int i = 0; i < threadCount; i++) {
			final int n = i + 1;
			pack.threads[i] = new Thread() {
				public void run() {
					if (debug) {
						System.out.println(" - started thread " + n + " / " + threadCount);
					}

					Parallel parallel;
					try {
						parallel = (Parallel) parallelClass.getConstructors()[0].newInstance(args);
					} catch (Exception e) {
						throw Errors.rte(e);
					}

					try {
						parallel.init(n);
						for (int j = 0; j < cyclesCount; j++) {
							if (THREADS_SYNC != null) {
								synchronized (THREADS_SYNC) {
									System.out.println("THREADS SYNC IN");
									parallel.run(n, j);
									System.out.println("THREADS SYNC OUT");
								}
							} else {
								parallel.run(n, j);
							}
						}
					} catch (Throwable e) {
						pack.error(e);
					}

					if (debug) {
						System.out.println(" - finished thread " + n + " / " + threadCount);
					}

					pack.done(parallel);
				}
			};
		}

		return pack;
	}

	protected void reload() {
		db.shutdown();
		db = Ohm.db(DB_FILE);
		DB_REF = new WeakReference(db);
	}

	@BeforeMethod
	public void cleanDB() {
		System.out.println("vvvvvvvvvvvv STARTING TEST " + getClass() + " - DB CLEAN-UP vvvvvvvvvvvv");

		U.delete(DB_FILE);

		db = Ohm.db(DB_FILE);
		DB_REF = new WeakReference(db);

		ids0to10 = Nums.fromTo(0, 10);

		OhmDB.setDefaultDb(db);
		ready();
	}

	@AfterMethod
	public void stopDB() {
		System.out.println("--------------- STOPPING DB --------------\n");
		db.shutdown();
		System.out.println("^^^^^^^^^^^^^^^ STOPPED DB ^^^^^^^^^^^^^^^\n");
	}

	protected void ready() {
	}

	protected void initSchema() {
		persons = db.table(Person.class);
		books = db.table(Book.class);
		tags = db.table(Tag.class);

		friends = db.manyToMany(persons, "friends", persons);

		wrote = db.oneToMany(persons, "wrote", books);
		writtenBy = wrote.inversed();

		follows = db.manyToMany(persons, "follows", tags);
		followedBy = follows.inversed();

		describes = db.manyToOne(tags, "describes", books);
		describedBy = describes.inversed();

		$p = persons.queryHelper();
		$b = books.queryHelper();
		$t = tags.queryHelper();
	}

	protected void initSchemaInMem() {
		System.out.println("Creating in-mem DB");
		db = Ohm.db();
		initSchema();
	}

	protected void initIndexing() {
		persons.createIndexOn($p.age);
		persons.createIndexOn($p.name);
		tags.createIndexOn($t.name);
		books.createIndexOn($b.published);
	}

	protected void initData10() {
		fillData10();
		initIndexing();
	}

	protected void fillData10() {
		initSchema();

		Fixtures.nickN(persons, 10, true);
		Fixtures.bookN(books, 10, true);
		Fixtures.tagN(tags, 10, true);

		Fixtures.relN(wrote, 0, 10, 10);
		Fixtures.relN(describedBy, 10, 20, 10);
		Fixtures.relN(follows, 0, 20, 10);
	}

	protected void checkData10() {
		Fixtures.nickN(persons, 10, false);
		Fixtures.bookN(books, 10, false);
		Fixtures.tagN(tags, 10, false);

		// FIXME check rels
	}

	protected char rndChar() {
		return (char) (65 + rnd(26));
	}

	protected String rndStr(int length) {
		return rndStr(length, length);
	}

	protected String rndStr(int minLength, int maxLength) {
		int len = minLength + rnd(maxLength - minLength + 1);
		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < len; i++) {
			sb.append(rndChar());
		}

		return sb.toString();
	}

	protected int rnd(int n) {
		return RND.nextInt(n);
	}

	protected int rndExcept(int n, int except) {
		Check.arg(n > 1 || except != 0, "Cannot produce such number!");
		while (true) {
			int num = RND.nextInt(n);
			if (num != except) {
				return num;
			}
		}
	}

	protected  T rnd(T[] arr) {
		return arr[rnd(arr.length)];
	}

	protected int rnd() {
		return RND.nextInt();
	}

	protected long rndL() {
		return RND.nextLong();
	}

	protected void expectedException() {
		Assert.fail("Expected exception!");
	}

	protected boolean yesNo() {
		return RND.nextBoolean();
	}

	protected void printIfNot(boolean expected, String errMsg) {
		if (!expected) {
			System.out.println(errMsg);
		}
	}

	protected void failIfNot(boolean expected, String errMsg) {
		if (!expected) {
			Assert.fail(errMsg);
		}
	}

	protected void tx() {
		TX = db.startTransaction();
	}

	protected void tx(AtomicInteger n) {
		TX = db.startTransaction();
		TX.addListener(txInc(n));
	}

	protected void rollback() {
		TX.rollback();
	}

	protected void commit() {
		TX.commit();
	}

	public String _(String format, Object... args) {
		return String.format(format, args);
	}

	protected void linky(Links[] links, Links[] links2) {
		System.out.println("=== REZ === " + Arrays.toString(links));
		System.out.println("=== EXP === " + Arrays.toString(links2));

		isTrue(UTILS.equal(links, links2));
	}

	protected void checkJoin(JoinConfig config, Links[] links2) {
		Links[] links = matcher().match(config);
		linky(links, links2);
	}

	protected long[] noln(int n) {
		return ln(n);
	}

	protected static RWRelation relation(Db db, Table from, String name, Table to) {
		return ((OhmDBImpl) db).relation(from, name, to);
	}

	public static RWRelation relation(Db db, String name) {
		return ((OhmDBImpl) db).relation(name);
	}

	public ReadOnlyRelation rel1(Db db) {
		RWRelation rel = relation(db, TBL1, "rel1", TBL2);

		UTILS.link(rel, 1, nums(20, 30));
		UTILS.link(rel, 2, nums(30, 40, 50));
		UTILS.link(rel, 7, nums(88));

		return rel;
	}

	public ReadOnlyRelation rel2(Db db) {
		RWRelation rel = relation(db, TBL2, "rel2", TBL3);

		UTILS.link(rel, 20, nums(200, 2000));
		UTILS.link(rel, 30, nums(333));
		UTILS.link(rel, 40, nums(400, 4000));
		UTILS.link(rel, 70, nums(777));

		return rel;
	}

	public ReadOnlyRelation rel3(Db db) {
		RWRelation rel = relation(db, TBL1, "rel3", TBL3);

		UTILS.link(rel, 1, nums(100, 2000));
		UTILS.link(rel, 2, nums(200, 2001));
		UTILS.link(rel, 3, nums(300, 3001));
		UTILS.link(rel, 4, nums(400, 4001));

		return rel;
	}

	public RWRelation rel10x10(String name, int fromBase, int toBase, Db db, Table tbl1, Table tbl2) {
		RWRelation rel = relation(db, tbl1, name, tbl2);

		for (int i = 0; i < 10; i++) {
			for (int j = 0; j <= 10; j++) {
				UTILS.link(rel, i + fromBase, nums(j + toBase));
			}
		}

		return rel;
	}

	public ReadOnlyRelation[] getR1R2(Db db) {
		return new ReadOnlyRelation[] { rel1(db), rel2(db) };
	}

	public ReadOnlyRelation[] getR1R2R3(Db db) {
		return new ReadOnlyRelation[] { rel1(db), rel2(db), rel3(db) };
	}

	public ReadOnlyRelation randomRel(Db db, String name, Table tbl1, Table tbl2, int max) {
		RWRelation rel = relation(db, tbl1, name, tbl2);

		rel.clear();
		int count = Nums.rnd(1, max);
		for (int i = 0; i < count; i++) {
			UTILS.link(rel, Nums.rnd(10), Nums.random(1, max, 0, max * 2));
		}

		return rel;
	}

	public ReadOnlyRelation[] randomRels(Db db, int max) {
		ReadOnlyRelation[] rels = new ReadOnlyRelation[Nums.rnd(2, 3)];

		Table tbl = new MockTable("TBL", Nums.arrFromTo(0, 1000));

		for (int i = 0; i < rels.length; i++) {
			rels[i] = randomRel(db, "rel" + i, tbl, tbl, max);
		}

		return rels;
	}

	public Numbers ids0() {
		return nums(0, 9);
	}

	public Numbers ids1() {
		return nums(10, 11, 12, 13, 14, 15, 20, 30, 40, 50);
	}

	public Numbers ids2() {
		return nums(100, 200, 300, 333, 400, 777);
	}

	protected Person p(long id) {
		Person person = new Person();
		person.id = id;
		return person;
	}

	protected Book b(long id) {
		Book book = new Book();
		book.id = id;
		return book;
	}

	protected void haveIds(Object[] objs, int... ids) {
		eq(objs.length, ids.length);
		for (int i = 0; i < ids.length; i++) {
			hasId(objs[i], ids[i]);
		}
	}

	protected void hasId(Object obj, int id) {
		eq(U.getId(obj), id);
	}

	protected void waitTx(DatastoreTransaction... txs) {
		U.sleep(1000); // FIXME
	}

	protected TransactionListener txInc(AtomicInteger n) {
		return new IncTransactionListener(n);
	}

	protected AtomicInteger atomN() {
		return new AtomicInteger();
	}

	protected LinkMatcher matcher() {
		return ((OhmDBImpl) db).getLinkMatcher();
	}

	protected Map storeMap() {
		return new HashMap();
	}

	private static Object[][] numN(int n) {
		Object[][] data = new Object[n][];

		for (int i = 0; i < data.length; i++) {
			data[i] = new Object[] { i };
		}

		return data;
	}

	@DataProvider
	public static Object[][] num2() {
		return numN(2);
	}

	@DataProvider
	public static Object[][] num3() {
		return numN(3);
	}

	@DataProvider
	public static Object[][] num4() {
		return numN(4);
	}

	@DataProvider
	public static Object[][] num5() {
		return numN(5);
	}

	@DataProvider
	public static Object[][] num10() {
		return numN(10);
	}

	@DataProvider
	public static Object[][] num50() {
		return numN(50);
	}

	@DataProvider
	public static Object[][] num100() {
		return numN(100);
	}

	@DataProvider
	public static Object[][] num200() {
		return numN(200);
	}

	@DataProvider
	public static Object[][] num500() {
		return numN(500);
	}

	@DataProvider
	public static Object[][] num1000() {
		return numN(1000);
	}

	@DataProvider
	public static Object[][] num5000() {
		return numN(5000);
	}

	@DataProvider
	public static Object[][] num10000() {
		return numN(10000);
	}

	@DataProvider
	public static Object[][] num50000() {
		return numN(50000);
	}

	@DataProvider
	public static Object[][] num100000() {
		return numN(100000);
	}

	protected static File tmpFile(String prefix, String suffix) {
		try {
			File file = File.createTempFile(prefix, suffix);
			file.deleteOnExit();
			return file;
		} catch (IOException e) {
			throw Errors.rte(e);
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy