Skip to content

Instantly share code, notes, and snippets.

@reyalpsirc
Created July 9, 2015 14:56
Show Gist options
  • Save reyalpsirc/ba4ecf3dda78564c1b2e to your computer and use it in GitHub Desktop.
Save reyalpsirc/ba4ecf3dda78564c1b2e to your computer and use it in GitHub Desktop.
Unit Test for issue 449 of CouchBase Lite .Net
using System;
using NUnit.Framework;
using Couchbase.Lite;
using System.Threading;
using Couchbase.Lite.Util;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Collections.Generic;
using Java.IO;
using System.Collections;
using System.Text;
using Org.Apache.Http.Util;
using Couchbase.Lite.Auth;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;
namespace Issue449
{
[TestFixture]
public class CouchDBReplication
{
const string Tag = "CouchDBReplication";
Database _db;
string attachDocId="b0c7add2-2c81-4882-b3d8-2d429b226890";
[SetUp]
public void Setup ()
{
}
[TearDown]
public void Tear ()
{
}
public void CheckDatabase(){
if (_db==null)
Assert.Inconclusive ("Database not set.");
}
protected void EnsureEmptyDatabase()
{
_db = Manager.SharedInstance.GetExistingDatabase("test");
if (_db != null)
{
var status = false;;
try {
_db.Delete();
status = true;
} catch (Exception e) {
Log.E(Tag, "Cannot delete database " + e.Message);
}
Assert.IsTrue(status);
}
_db = Manager.SharedInstance.GetDatabase("test");
}
public void CreateDocuments(Database db, int n)
{
//TODO should be changed to use db.runInTransaction
for (int i = 0; i < n; i++)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
properties.Add("testName", "testDatabase");
properties.Add("sequence", i);
CreateDocumentWithProperties(db, properties);
}
}
private int CountIenumerable(IEnumerable e){
int total = 0;
foreach (var v in e) {
total++;
}
return total;
}
/// <exception cref="System.Exception"></exception>
public Document CreateDocWithAttachment(Database database, string attachmentName
, string content)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
properties.Add("foo", "bar");
Document doc = CreateDocumentWithProperties(database, properties);
SavedRevision rev = doc.CurrentRevision;
NUnit.Framework.Assert.AreEqual(CountIenumerable(rev.Attachments), 0);
NUnit.Framework.Assert.AreEqual(CountIenumerable(rev.AttachmentNames), 0);
NUnit.Framework.Assert.IsNull(rev.GetAttachment(attachmentName));
UnsavedRevision rev2 = doc.CreateRevision();
rev2.SetAttachment(attachmentName, "text/plain; charset=utf-8", Encoding.UTF8.GetBytes(content));
SavedRevision rev3 = rev2.Save();
NUnit.Framework.Assert.IsNotNull(rev3);
NUnit.Framework.Assert.AreEqual(CountIenumerable(rev3.Attachments), 1);
NUnit.Framework.Assert.AreEqual(CountIenumerable(rev3.AttachmentNames), 1);
Attachment attach = rev3.GetAttachment(attachmentName);
NUnit.Framework.Assert.IsNotNull(attach);
NUnit.Framework.Assert.AreEqual(doc, attach.Document);
NUnit.Framework.Assert.AreEqual(attachmentName, attach.Name);
IList<string> attNames = new List<string>();
attNames.Add(attachmentName);
NUnit.Framework.Assert.AreEqual(rev3.AttachmentNames, attNames);
NUnit.Framework.Assert.AreEqual("text/plain; charset=utf-8", attach.ContentType);
NUnit.Framework.Assert.AreEqual(Encoding.UTF8.GetString(attach.Content.ToArray()), content);
NUnit.Framework.Assert.AreEqual(Encoding.UTF8.GetBytes(content).Length
, attach.Length);
return doc;
}
private Document CreateDocumentWithProperties(Database db, IDictionary<string, object> properties)
{
var doc = db.CreateDocument();
Assert.IsNotNull(doc);
Assert.IsNull(doc.CurrentRevisionId);
Assert.IsNull(doc.CurrentRevision);
Assert.IsNotNull(doc.Id, "Document has no ID");
try
{
doc.PutProperties(properties);
}
catch (Exception e)
{
Log.E(Tag, "Error creating document", e);
Assert.IsTrue(false, "can't create new document in db:" + db.Name + " with properties:" + properties.ToString());
}
Assert.IsNotNull(doc.Id);
Assert.IsNotNull(doc.CurrentRevisionId);
Assert.IsNotNull(doc.CurrentRevision);
// should be same doc instance, since there should only ever be a single Document instance for a given document
Assert.AreEqual(db.GetDocument(doc.Id), doc);
Assert.AreEqual(db.GetDocument(doc.Id).Id, doc.Id);
return doc;
}
private void RunReplication(Replication replication, int total_records)
{
Log.D(Tag, "replicator start");
replication.Start();
var t = TaskOfReplication (replication);
t.Start ();
var finished=t.Wait (60000);
Assert.IsTrue(finished);
Log.D(Tag, "replicator finished");
//replication.Changed -= changed;
}
private Task TaskOfReplication (Replication replication)
{
return new Task(delegate{
var started=false;
while (true)
{
if (replication.IsRunning)
{
started = true;
}
var statusIsDone = (
replication.Status == ReplicationStatus.Stopped
|| replication.Status == ReplicationStatus.Idle
);
if (started && statusIsDone)
{
break;
}
try
{
Thread.Sleep(1000);
}
catch (Exception e)
{
Debug.WriteLine(e);
}
}
});
}
public async Task<JObject> FetchAllDocs(string url)
{
JObject result = null;
try {
//Setup the HTTPClient with or without the cookie
if (url[url.Length-1]!='/'){
url+="/";
}
//Debug.WriteLine ("fetch documents on " + url);
HttpClient client = new HttpClient ();
client.DefaultRequestHeaders.Accept.Add (new MediaTypeWithQualityHeaderValue ("application/json"));
client.DefaultRequestHeaders.Add ("Accept-Charset", "utf-8");
//Make the request
var response=await client.GetAsync (url+"_all_docs").ConfigureAwait(false);
var responseString = await response.Content.ReadAsStringAsync ().ConfigureAwait(false);
result = JObject.Parse (responseString);
} catch (Exception ex){
Debug.WriteLine(ex);
}
return result;
}
public async Task<bool> DeleteAllOnServer(string url)
{
bool result = false;
try {
//Setup the HTTPClient with or without the cookie
if (url[url.Length-1]!='/'){
url+="/";
}
JObject json = await FetchAllDocs(url).ConfigureAwait(false);
Assert.IsTrue(json != null);
Assert.IsTrue(json ["rows"] != null);
JArray data = (JArray)json ["rows"];
if (data.Count > 0) {
//Backup:
var docs=new JObject();
docs ["docs"] = data;
foreach (var d in data) {
JObject theObj = (JObject)d ["value"];
if (theObj != null) {
string id=(string)d["id"];
string rev=(string)theObj ["rev"];
Assert.IsTrue(id!=null);
Assert.IsTrue(rev!=null);
HttpClient client2 = new HttpClient ();
client2.DefaultRequestHeaders.Accept.Add (new MediaTypeWithQualityHeaderValue ("application/json"));
client2.DefaultRequestHeaders.Add ("Accept-Charset", "utf-8");
System.Console.WriteLine("Deleting "+id);
var t3 = client2.DeleteAsync (new Uri (url+ id + "/?rev=" + rev));
t3.Wait ();
Assert.IsTrue(t3.Result.IsSuccessStatusCode);
}
}
result=true;
} else {
result=true;
}
} catch (Exception ex){
Debug.WriteLine(ex);
}
return result;
}
[Test]
public void MainTest ()
{
ClearRemoteDB ();
CreateDatabase ();
EnsureEmptyDatabase ();
StartPushReplication ();
ChangeDocuments ("5");
StartChangedPushReplication ();
EnsureEmptyDatabase ();
StartPullReplication ();
ChangeDocuments ("10");
StartChangedPushReplication ();
ClearRemoteDB ();
}
public void ClearRemoteDB()
{
var deleteTask = DeleteAllOnServer ("http://reyalpsirc.iriscouch.com/test");
deleteTask.Wait();
Assert.IsTrue (deleteTask.Result);
//Purge
HttpClient client = new HttpClient ();
client.DefaultRequestHeaders.Accept.Add (new MediaTypeWithQualityHeaderValue ("application/json"));
client.DefaultRequestHeaders.Add ("Accept-Charset", "utf-8");
var body = new StringContent ((new JObject()).ToString());
body.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue( "application/json");
var t = client.PostAsync (new Uri ("http://reyalpsirc.iriscouch.com/test/_purge"),body);
t.Wait ();
Assert.IsTrue(t.Result.IsSuccessStatusCode);
//Check records
var t2=FetchAllDocs("http://reyalpsirc.iriscouch.com/test");
t2.Wait();
JObject json = t2.Result;
Assert.IsTrue(json != null);
Assert.IsTrue(json ["rows"] != null);
JArray data = (JArray)json ["rows"];
Assert.IsTrue(data.Count == 0);
}
public void CreateDatabase ()
{
_db = Manager.SharedInstance.GetExistingDatabase ("test");
if (_db == null) {
_db = Manager.SharedInstance.GetDatabase ("test");
}
Assert.True (_db!=null);
}
public void StartPushReplication()
{
var push = _db.CreatePushReplication(new Uri("http://reyalpsirc.iriscouch.com/test"));
CreateDocuments(_db, 2);
var attachDoc = CreateDocWithAttachment(_db, "attachment.png", "image/png");
attachDocId = attachDoc.Id;
RunReplication(push,3);
Assert.IsTrue(push.ChangesCount==3);
Assert.IsTrue(push.CompletedChangesCount==3);
Assert.IsNull(push.LastError);
Assert.AreEqual(3, _db.DocumentCount);
attachDoc = _db.GetExistingDocument(attachDocId);
Assert.IsNotNull(attachDoc, "Failed to store doc with attachment");
Assert.IsNotNull(attachDoc.CurrentRevision.Attachments, "Failed to store attachments on attachment doc");
}
public void StartPullReplication()
{
var pull = _db.CreatePullReplication(new Uri("http://reyalpsirc.iriscouch.com/test"));
Assert.AreEqual(0, _db.DocumentCount);
RunReplication(pull,3);
Assert.IsNull(pull.LastError);
Assert.AreEqual(3, _db.DocumentCount);
var attachDoc = _db.GetExistingDocument(attachDocId);
Assert.IsNotNull(attachDoc, "Failed to retrieve doc with attachment");
Assert.IsNotNull(attachDoc.CurrentRevision.Attachments, "Failed to retrieve attachments on attachment doc");
}
public void ChangeDocuments(string extraminutes)
{
var attachDoc = _db.GetExistingDocument(attachDocId);
Assert.IsNotNull(attachDoc, "Failed to retrieve doc with attachment");
Assert.IsNotNull(attachDoc.CurrentRevision.Attachments, "Failed to retrieve attachments on attachment doc");
var properties = attachDoc.Properties;
if (properties.ContainsKey ("extraminutes"))
properties ["extraminutes"] = extraminutes;
else
properties.Add("extraminutes", extraminutes);
attachDoc.PutProperties (properties);
var checkAttach = _db.GetExistingDocument(attachDocId);
Assert.IsTrue(checkAttach.Properties.ContainsKey("extraminutes"));
Assert.IsTrue((string)checkAttach.Properties ["extraminutes"]==extraminutes);
}
public void StartChangedPushReplication()
{
var push = _db.CreatePushReplication(new Uri("http://reyalpsirc.iriscouch.com/test"));
RunReplication(push,1);
Assert.IsTrue(push.ChangesCount==1);
Assert.IsTrue(push.CompletedChangesCount==1);
Assert.IsNull(push.LastError);
Assert.AreEqual(3, _db.DocumentCount);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment