1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2009 Oracle.  All rights reserved.
5 *
6 */
7using System;
8using System.Collections;
9using System.Collections.Generic;
10using System.IO;
11using System.Text;
12using System.Threading;
13using System.Xml;
14using NUnit.Framework;
15using BerkeleyDB;
16
17namespace CsharpAPITest
18{
19	[TestFixture]
20	public class JoinCursorTest
21	{
22		private string testFixtureHome;
23		private string testFixtureName;
24		private string testName;
25		private string testHome;
26
27		[TestFixtureSetUp]
28		public void RunBeforeTests()
29		{
30			testFixtureName = "JoinCursorTest";
31			testFixtureHome = "./TestOut/" + testFixtureName;
32
33			Configuration.ClearDir(testFixtureHome);
34		}
35
36		[Test]
37		public void TestJoin()
38		{
39			testName = "TestJoin";
40			testHome = testFixtureHome + "/" + testName;
41			string dbFileName = testHome + "/" + testName + ".db";
42			string secFileName1 = testHome + "/" + "sec_" + testName + "1.db";
43			string secFileName2 = testHome + "/" + "sec_" + testName + "2.db";
44
45			Configuration.ClearDir(testHome);
46
47			// Open a primary database.
48			BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
49			dbCfg.Creation = CreatePolicy.IF_NEEDED;
50			BTreeDatabase db = BTreeDatabase.Open(dbFileName, dbCfg);
51
52			/*
53			 * Open two databases, their secondary databases and
54			 * secondary cursors.
55			 */
56			SecondaryBTreeDatabase secDB1, secDB2;
57			SecondaryCursor[] cursors = new SecondaryCursor[2];
58			GetSecCursor(db, secFileName1,
59			    new SecondaryKeyGenDelegate(KeyGenOnBigByte),
60			    out secDB1, out cursors[0], false, null);
61			GetSecCursor(db, secFileName2,
62			    new SecondaryKeyGenDelegate(KeyGenOnLittleByte),
63			    out secDB2, out cursors[1], true, null);
64
65			// Get join cursor.
66			JoinCursor joinCursor = db.Join(cursors, true);
67
68			// Close all.
69			joinCursor.Close();
70			cursors[0].Close();
71			cursors[1].Close();
72			secDB1.Close();
73			secDB2.Close();
74			db.Close();
75		}
76
77		[Test]
78		public void TestMoveJoinCursor()
79		{
80			testName = "TestMoveJoinCursor";
81			testHome = testFixtureHome + "/" + testName;
82			string dbFileName = testHome + "/" + testName + ".db";
83			string secFileName1 = testHome + "/" + "sec_" + testName + "1.db";
84			string secFileName2 = testHome + "/" + "sec_" + testName + "2.db";
85
86			Configuration.ClearDir(testHome);
87
88			// Open a primary database.
89			BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
90			dbCfg.Creation = CreatePolicy.IF_NEEDED;
91			BTreeDatabase db = BTreeDatabase.Open(dbFileName, dbCfg);
92
93			/*
94			 * Open a secondary database on high byte of
95			 * its data and another secondary database on
96			 * little byte of its data.
97			 */
98			SecondaryBTreeDatabase secDB1, secDB2;
99			SecondaryCursor[] cursors = new SecondaryCursor[2];
100			byte[] byteValue = new byte[1];
101
102			byteValue[0] = 0;
103			GetSecCursor(db, secFileName1,
104			    new SecondaryKeyGenDelegate(KeyGenOnBigByte),
105			    out secDB1, out cursors[0], false,
106			    new DatabaseEntry(byteValue));
107
108			byteValue[0] = 1;
109			GetSecCursor(db, secFileName2,
110			    new SecondaryKeyGenDelegate(KeyGenOnLittleByte),
111			    out secDB2, out cursors[1], true,
112			    new DatabaseEntry(byteValue));
113
114			// Get join cursor.
115			JoinCursor joinCursor = db.Join(cursors, true);
116
117			/*
118			 * MoveNextJoinItem do not use data value found
119			 * in all of the cursor so the data in Current won't be
120			 * changed.
121			 */
122			Assert.IsTrue(joinCursor.MoveNextItem());
123			Assert.AreEqual(0, joinCursor.Current.Key.Data[
124			    joinCursor.Current.Key.Data.Length - 1]);
125			Assert.AreEqual(1, joinCursor.Current.Key.Data[0]);
126			Assert.IsNull(joinCursor.Current.Value.Data);
127
128			// Iterate on join cursor.
129			foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> pair in joinCursor)
130			{
131				/*
132				 * Confirm that the key got by join cursor has 0 at
133				 * its highest byte and 1 at its lowest byte.
134				 */
135				Assert.AreEqual(0, pair.Key.Data[pair.Key.Data.Length - 1]);
136				Assert.AreEqual(1, pair.Key.Data[0]);
137			}
138
139			Assert.IsFalse(joinCursor.MoveNext());
140
141			// Close all.
142			joinCursor.Close();
143			cursors[0].Close();
144			cursors[1].Close();
145			secDB1.Close();
146			secDB2.Close();
147			db.Close();
148		}
149
150		public void GetSecCursor(BTreeDatabase db,
151		    string secFileName, SecondaryKeyGenDelegate keyGen,
152		    out SecondaryBTreeDatabase secDB,
153		    out SecondaryCursor cursor, bool ifCfg,
154		    DatabaseEntry data)
155		{
156			// Open secondary database.
157			SecondaryBTreeDatabaseConfig secCfg =
158			    new SecondaryBTreeDatabaseConfig(db, keyGen);
159			secCfg.Creation = CreatePolicy.IF_NEEDED;
160			secCfg.Duplicates = DuplicatesPolicy.SORTED;
161			secDB = SecondaryBTreeDatabase.Open(secFileName, secCfg);
162
163			int[] intArray = new int[4];
164			intArray[0] = 0;
165			intArray[1] = 1;
166			intArray[2] = 2049;
167			intArray[3] = 65537;
168			for (int i = 0; i < 4; i++)
169			{
170				DatabaseEntry record = new DatabaseEntry(
171				    BitConverter.GetBytes(intArray[i]));
172				db.Put(record, record);
173			}
174
175			// Get secondary cursor on the secondary database.
176			if (ifCfg == false)
177				cursor = secDB.SecondaryCursor();
178			else
179				cursor = secDB.SecondaryCursor(new CursorConfig());
180
181			// Position the cursor.
182			if (data != null)
183				Assert.IsTrue(cursor.Move(data, true));
184		}
185
186		public DatabaseEntry KeyGenOnLittleByte(
187		    DatabaseEntry key, DatabaseEntry data)
188		{
189			byte[] byteArr = new byte[1];
190			byteArr[0] = data.Data[0];
191			DatabaseEntry dbtGen = new DatabaseEntry(byteArr);
192			return dbtGen;
193		}
194
195		public DatabaseEntry KeyGenOnBigByte(
196		    DatabaseEntry key, DatabaseEntry data)
197		{
198			byte[] byteArr = new byte[1];
199			byteArr[0] = data.Data[data.Data.Length - 1];
200			DatabaseEntry dbtGen = new DatabaseEntry(byteArr);
201			return dbtGen;
202		}
203	}
204}
205