本文整理汇总了C#中Sharpen.CountDownLatch.Await方法的典型用法代码示例。如果您正苦于以下问题:C# CountDownLatch.Await方法的具体用法?C# CountDownLatch.Await怎么用?C# CountDownLatch.Await使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Sharpen.CountDownLatch
的用法示例。
在下文中一共展示了CountDownLatch.Await方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: ChangeTrackerTestWithMode
/// <exception cref="System.Exception"></exception>
public virtual void ChangeTrackerTestWithMode(ChangeTracker.ChangeTrackerMode mode
, bool useMockReplicator)
{
CountDownLatch changeTrackerFinishedSignal = new CountDownLatch(1);
CountDownLatch changeReceivedSignal = new CountDownLatch(1);
Uri testURL = GetReplicationURL();
ChangeTrackerClient client = new _ChangeTrackerClient_42(changeTrackerFinishedSignal
, useMockReplicator, changeReceivedSignal);
ChangeTracker changeTracker = new ChangeTracker(testURL, mode, false, 0, client);
changeTracker.SetUsePOST(IsTestingAgainstSyncGateway());
changeTracker.Start();
try
{
bool success = changeReceivedSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue(success);
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
changeTracker.Stop();
try
{
bool success = changeTrackerFinishedSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue(success);
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
}
示例2: TestChangeTracker
/// <exception cref="System.Exception"></exception>
public virtual void TestChangeTracker()
{
CountDownLatch changeTrackerFinishedSignal = new CountDownLatch(1);
Uri testURL = GetReplicationURL();
ChangeTrackerClient client = new _ChangeTrackerClient_31(changeTrackerFinishedSignal
);
ChangeTracker changeTracker = new ChangeTracker(testURL, ChangeTracker.ChangeTrackerMode
.OneShot, 0, client);
changeTracker.Start();
try
{
bool success = changeTrackerFinishedSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue(success);
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
}
开发者ID:transformersprimeabcxyz,项目名称:_TO-DO-couchbase-lite-net-couchbase,代码行数:20,代码来源:ChangeTrackerTest.cs
示例3: Await
private static void Await(CountDownLatch cdl)
{
try
{
NUnit.Framework.Assert.IsTrue(cdl.Await(1000, TimeUnit.MILLISECONDS), "latch released"
);
}
catch (Exception)
{
NUnit.Framework.Assert.Fail("Did not expect to be interrupted");
}
}
示例4: TestChangeTracking
//CHANGE TRACKING
/// <exception cref="System.Exception"></exception>
public virtual void TestChangeTracking()
{
CountDownLatch doneSignal = new CountDownLatch(1);
Database db = StartDatabase();
db.AddChangeListener(new _ChangeListener_579(doneSignal));
CreateDocumentsAsync(db, 5);
// We expect that the changes reported by the server won't be notified, because those revisions
// are already cached in memory.
bool success = doneSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue(success);
NUnit.Framework.Assert.AreEqual(5, db.GetLastSequenceNumber());
}
示例5: TestPusher
/// <exception cref="System.Exception"></exception>
public virtual void TestPusher()
{
CountDownLatch replicationDoneSignal = new CountDownLatch(1);
Uri remote = GetReplicationURL();
string docIdTimestamp = System.Convert.ToString(Runtime.CurrentTimeMillis());
// Create some documents:
IDictionary<string, object> documentProperties = new Dictionary<string, object>();
string doc1Id = string.Format("doc1-%s", docIdTimestamp);
documentProperties.Put("_id", doc1Id);
documentProperties.Put("foo", 1);
documentProperties.Put("bar", false);
Body body = new Body(documentProperties);
RevisionInternal rev1 = new RevisionInternal(body, database);
Status status = new Status();
rev1 = database.PutRevision(rev1, null, false, status);
NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode());
documentProperties.Put("_rev", rev1.GetRevId());
documentProperties.Put("UPDATED", true);
RevisionInternal rev2 = database.PutRevision(new RevisionInternal(documentProperties
, database), rev1.GetRevId(), false, status);
NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode());
documentProperties = new Dictionary<string, object>();
string doc2Id = string.Format("doc2-%s", docIdTimestamp);
documentProperties.Put("_id", doc2Id);
documentProperties.Put("baz", 666);
documentProperties.Put("fnord", true);
database.PutRevision(new RevisionInternal(documentProperties, database), null, false
, status);
NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode());
bool continuous = false;
Replication repl = database.CreatePushReplication(remote);
repl.SetContinuous(continuous);
repl.SetCreateTarget(true);
// Check the replication's properties:
NUnit.Framework.Assert.AreEqual(database, repl.GetLocalDatabase());
NUnit.Framework.Assert.AreEqual(remote, repl.GetRemoteUrl());
NUnit.Framework.Assert.IsFalse(repl.IsPull());
NUnit.Framework.Assert.IsFalse(repl.IsContinuous());
NUnit.Framework.Assert.IsTrue(repl.ShouldCreateTarget());
NUnit.Framework.Assert.IsNull(repl.GetFilter());
NUnit.Framework.Assert.IsNull(repl.GetFilterParams());
// TODO: CAssertNil(r1.doc_ids);
// TODO: CAssertNil(r1.headers);
// Check that the replication hasn't started running:
NUnit.Framework.Assert.IsFalse(repl.IsRunning());
NUnit.Framework.Assert.AreEqual(Replication.ReplicationStatus.ReplicationStopped,
repl.GetStatus());
NUnit.Framework.Assert.AreEqual(0, repl.GetCompletedChangesCount());
NUnit.Framework.Assert.AreEqual(0, repl.GetChangesCount());
NUnit.Framework.Assert.IsNull(repl.GetLastError());
RunReplication(repl);
// make sure doc1 is there
// TODO: make sure doc2 is there (refactoring needed)
Uri replicationUrlTrailing = new Uri(string.Format("%s/", remote.ToExternalForm()
));
Uri pathToDoc = new Uri(replicationUrlTrailing, doc1Id);
Log.D(Tag, "Send http request to " + pathToDoc);
CountDownLatch httpRequestDoneSignal = new CountDownLatch(1);
BackgroundTask getDocTask = new _BackgroundTask_122(pathToDoc, doc1Id, httpRequestDoneSignal
);
//Closes the connection.
getDocTask.Execute();
Log.D(Tag, "Waiting for http request to finish");
try
{
httpRequestDoneSignal.Await(300, TimeUnit.Seconds);
Log.D(Tag, "http request finished");
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
Log.D(Tag, "testPusher() finished");
}
示例6: RunLiveQuery
// kick something off that will s
/// <exception cref="System.Exception"></exception>
public virtual void RunLiveQuery(string methodNameToCall)
{
Database db = StartDatabase();
CountDownLatch doneSignal = new CountDownLatch(11);
// 11 corresponds to startKey=23; endKey=33
// run a live query
View view = db.GetView("vu");
view.SetMap(new _Mapper_817(), "1");
LiveQuery query = view.CreateQuery().ToLiveQuery();
query.SetStartKey(23);
query.SetEndKey(33);
Log.I(Tag, "Created " + query);
// these are the keys that we expect to see in the livequery change listener callback
ICollection<int> expectedKeys = new HashSet<int>();
for (int i = 23; i < 34; i++)
{
expectedKeys.AddItem(i);
}
// install a change listener which decrements countdown latch when it sees a new
// key from the list of expected keys
LiveQuery.ChangeListener changeListener = new _ChangeListener_836(expectedKeys, doneSignal
);
query.AddChangeListener(changeListener);
// create the docs that will cause the above change listener to decrement countdown latch
int kNDocs = 50;
CreateDocumentsAsync(db, kNDocs);
if (methodNameToCall.Equals("start"))
{
// start the livequery running asynchronously
query.Start();
}
else
{
if (methodNameToCall.Equals("startWaitForRows"))
{
query.Start();
query.WaitForRows();
}
else
{
NUnit.Framework.Assert.IsNull(query.GetRows());
query.Run();
// this will block until the query completes
NUnit.Framework.Assert.IsNotNull(query.GetRows());
}
}
// wait for the doneSignal to be finished
bool success = doneSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue("Done signal timed out, live query never ran", success
);
// stop the livequery since we are done with it
query.RemoveChangeListener(changeListener);
query.Stop();
}
示例7: TestChangeListenerNotificationBatching
public void TestChangeListenerNotificationBatching()
{
const int numDocs = 50;
var atomicInteger = 0;
var doneSignal = new CountDownLatch(1);
database.Changed += (sender, e) => Interlocked.Increment (ref atomicInteger);
database.RunInTransaction(() =>
{
CreateDocuments(database, numDocs);
doneSignal.CountDown();
return true;
});
var success = doneSignal.Await(TimeSpan.FromSeconds(30));
Assert.IsTrue(success);
Assert.AreEqual(1, atomicInteger);
}
示例8: ChangeTrackerTestWithMode
private void ChangeTrackerTestWithMode(ChangeTrackerMode mode)
{
var changeTrackerFinishedSignal = new CountDownLatch(1);
var changeReceivedSignal = new CountDownLatch(1);
var client = new ChangeTrackerTestClient(changeTrackerFinishedSignal, changeReceivedSignal);
client.ReceivedChangeDelegate = (IDictionary<string, object> change) =>
{
Assert.IsTrue(change.ContainsKey("seq"));
Assert.AreEqual("1", change["seq"]);
};
var handler = client.HttpRequestHandler;
handler.SetResponder("_changes", (request) =>
{
var json = "{\"results\":[\n" +
"{\"seq\":\"1\",\"id\":\"doc1-138\",\"changes\":[{\"rev\":\"1-82d\"}]}],\n" +
"\"last_seq\":\"*:50\"}";
return MockHttpRequestHandler.GenerateHttpResponseMessage(HttpStatusCode.OK, null, json);
});
var testUrl = GetReplicationURL();
var scheduler = new SingleTaskThreadpoolScheduler();
var changeTracker = new ChangeTracker(testUrl, mode, 0, false, client, new TaskFactory(scheduler));
changeTracker.UsePost = IsSyncGateway(testUrl);
changeTracker.Start();
var success = changeReceivedSignal.Await(TimeSpan.FromSeconds(30));
Assert.IsTrue(success);
changeTracker.Stop();
success = changeTrackerFinishedSignal.Await(TimeSpan.FromSeconds(30));
Assert.IsTrue(success);
}
示例9: RunChangeTrackerTransientError
private void RunChangeTrackerTransientError(
ChangeTrackerMode mode,
Int32 errorCode,
string statusMessage,
Int32 numExpectedChangeCallbacks)
{
var changeTrackerFinishedSignal = new CountDownLatch(1);
var changeReceivedSignal = new CountDownLatch(numExpectedChangeCallbacks);
var client = new ChangeTrackerTestClient(changeTrackerFinishedSignal, changeReceivedSignal);
MockHttpRequestHandler.HttpResponseDelegate sentinal = RunChangeTrackerTransientErrorDefaultResponder();
var responders = new List<MockHttpRequestHandler.HttpResponseDelegate>();
responders.Add(RunChangeTrackerTransientErrorDefaultResponder());
responders.Add(MockHttpRequestHandler.TransientErrorResponder(errorCode, statusMessage));
MockHttpRequestHandler.HttpResponseDelegate chainResponder = (request) =>
{
if (responders.Count > 0) {
var responder = responders[0];
responders.RemoveAt(0);
return responder(request);
}
return sentinal(request);
};
var handler = client.HttpRequestHandler;
handler.SetResponder("_changes", chainResponder);
var testUrl = GetReplicationURL();
var scheduler = new SingleTaskThreadpoolScheduler();
var changeTracker = new ChangeTracker(testUrl, mode, 0, false, client, new TaskFactory(scheduler));
changeTracker.UsePost = IsSyncGateway(testUrl);
changeTracker.Start();
var success = changeReceivedSignal.Await(TimeSpan.FromSeconds(30));
Assert.IsTrue(success);
changeTracker.Stop();
success = changeTrackerFinishedSignal.Await(TimeSpan.FromSeconds(30));
Assert.IsTrue(success);
}
示例10: ChangeTrackerTestWithMode
/// <exception cref="System.Exception"></exception>
public virtual void ChangeTrackerTestWithMode(ChangeTracker.ChangeTrackerMode mode
)
{
CountDownLatch changeTrackerFinishedSignal = new CountDownLatch(1);
CountDownLatch changeReceivedSignal = new CountDownLatch(1);
Uri testURL = GetReplicationURL();
IChangeTrackerClient client = new _ChangeTrackerClient_119(changeTrackerFinishedSignal
, changeReceivedSignal);
ChangeTracker changeTracker = new ChangeTracker(testURL, mode, 0, client);
changeTracker.Start();
try
{
bool success = changeReceivedSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue(success);
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
changeTracker.Stop();
try
{
bool success = changeTrackerFinishedSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue(success);
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
}
示例11: TestChangeTrackerBackoff
/// <exception cref="System.Exception"></exception>
private void TestChangeTrackerBackoff(CustomizableMockHttpClient mockHttpClient)
{
Uri testURL = GetReplicationURL();
CountDownLatch changeTrackerFinishedSignal = new CountDownLatch(1);
ChangeTrackerClient client = new _ChangeTrackerClient_234(changeTrackerFinishedSignal
, mockHttpClient);
ChangeTracker changeTracker = new ChangeTracker(testURL, ChangeTracker.ChangeTrackerMode
.LongPoll, false, 0, client);
changeTracker.Start();
// sleep for a few seconds
Sharpen.Thread.Sleep(5 * 1000);
// make sure we got less than 10 requests in those 10 seconds (if it was hammering, we'd get a lot more)
NUnit.Framework.Assert.IsTrue(mockHttpClient.GetCapturedRequests().Count < 25);
NUnit.Framework.Assert.IsTrue(changeTracker.backoff.GetNumAttempts() > 0);
mockHttpClient.ClearResponders();
mockHttpClient.AddResponderReturnEmptyChangesFeed();
// at this point, the change tracker backoff should cause it to sleep for about 3 seconds
// and so lets wait 3 seconds until it wakes up and starts getting valid responses
Sharpen.Thread.Sleep(3 * 1000);
// now find the delta in requests received in a 2s period
int before = mockHttpClient.GetCapturedRequests().Count;
Sharpen.Thread.Sleep(2 * 1000);
int after = mockHttpClient.GetCapturedRequests().Count;
// assert that the delta is high, because at this point the change tracker should
// be hammering away
NUnit.Framework.Assert.IsTrue((after - before) > 25);
// the backoff numAttempts should have been reset to 0
NUnit.Framework.Assert.IsTrue(changeTracker.backoff.GetNumAttempts() == 0);
changeTracker.Stop();
try
{
bool success = changeTrackerFinishedSignal.Await(300, TimeUnit.Seconds);
NUnit.Framework.Assert.IsTrue(success);
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
}
示例12: TestPusherDeletedDoc
public virtual void TestPusherDeletedDoc()
{
Assert.Fail(); // TODO.ZJG: Needs debugging, overflows stack.
CountDownLatch replicationDoneSignal = new CountDownLatch(1);
Uri remote = GetReplicationURL();
string docIdTimestamp = System.Convert.ToString(Runtime.CurrentTimeMillis());
// Create some documentsConvert
IDictionary<string, object> documentProperties = new Dictionary<string, object>();
string doc1Id = string.Format("doc1-{0}", docIdTimestamp);
documentProperties["_id"] = doc1Id;
documentProperties["foo"] = 1;
documentProperties["bar"] = false;
Body body = new Body(documentProperties);
RevisionInternal rev1 = new RevisionInternal(body, database);
Status status = new Status();
rev1 = database.PutRevision(rev1, null, false, status);
NUnit.Framework.Assert.AreEqual(StatusCode.Created, status.GetCode());
documentProperties["_rev"] = rev1.GetRevId();
documentProperties["UPDATED"] = true;
documentProperties["_deleted"] = true;
RevisionInternal rev2 = database.PutRevision(new RevisionInternal(documentProperties
, database), rev1.GetRevId(), false, status);
NUnit.Framework.Assert.IsTrue((int)status.GetCode() >= 200 && (int)status.GetCode() < 300);
var repl = database.CreatePushReplication(remote);
((Pusher)repl).CreateTarget = true;
RunReplication(repl);
// make sure doc1 is deleted
Uri replicationUrlTrailing = new Uri(string.Format("{0}/", remote.ToString()
));
Uri pathToDoc = new Uri(replicationUrlTrailing, doc1Id);
Log.D(Tag, "Send http request to " + pathToDoc);
CountDownLatch httpRequestDoneSignal = new CountDownLatch(1);
var getDocTask = Task.Factory.StartNew(()=>
{
var httpclient = new HttpClient();
HttpResponseMessage response;
string responseString = null;
try
{
var responseTask = httpclient.GetAsync(pathToDoc.ToString());
responseTask.Wait();
response = responseTask.Result;
var statusLine = response.StatusCode;
Log.D(ReplicationTest.Tag, "statusLine " + statusLine);
Assert.AreEqual(HttpStatusCode.NotFound, statusLine.GetStatusCode());
}
catch (ProtocolViolationException e)
{
NUnit.Framework.Assert.IsNull(e, "Got ClientProtocolException: " + e.Message);
}
catch (IOException e)
{
NUnit.Framework.Assert.IsNull(e, "Got IOException: " + e.Message);
}
finally
{
httpRequestDoneSignal.CountDown();
}
});
getDocTask.Start();
Log.D(Tag, "Waiting for http request to finish");
try
{
httpRequestDoneSignal.Await(TimeSpan.FromSeconds(10));
Log.D(Tag, "http request finished");
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
Log.D(Tag, "testPusherDeletedDoc() finished");
}
示例13: TestPusher
//.........这里部分代码省略.........
var body = new Body(documentProperties);
var rev1 = new RevisionInternal(body, database);
var status = new Status();
rev1 = database.PutRevision(rev1, null, false, status);
Assert.AreEqual(StatusCode.Created, status.GetCode());
documentProperties.Put("_rev", rev1.GetRevId());
documentProperties["UPDATED"] = true;
var rev2 = database.PutRevision(new RevisionInternal(documentProperties, database), rev1.GetRevId(), false, status);
Assert.AreEqual(StatusCode.Created, status.GetCode());
documentProperties = new Dictionary<string, object>();
var doc2Id = string.Format("doc2-{0}", docIdTimestamp);
documentProperties["_id"] = doc2Id;
documentProperties["baz"] = 666;
documentProperties["fnord"] = true;
database.PutRevision(new RevisionInternal(documentProperties, database), null, false, status);
Assert.AreEqual(StatusCode.Created, status.GetCode());
var continuous = false;
var repl = database.CreatePushReplication(remote);
repl.Continuous = continuous;
//repl.CreateTarget = false;
// Check the replication's properties:
Assert.AreEqual(database, repl.LocalDatabase);
Assert.AreEqual(remote, repl.RemoteUrl);
Assert.IsFalse(repl.IsPull);
Assert.IsFalse(repl.Continuous);
//Assert.IsTrue(repl.CreateTarget);
Assert.IsNull(repl.Filter);
Assert.IsNull(repl.FilterParams);
// TODO: CAssertNil(r1.doc_ids);
// TODO: CAssertNil(r1.headers);
// Check that the replication hasn't started running:
Assert.IsFalse(repl.IsRunning);
Assert.AreEqual((int)repl.Status, (int)ReplicationStatus.Stopped);
Assert.AreEqual(0, repl.CompletedChangesCount);
Assert.AreEqual(0, repl.ChangesCount);
Assert.IsNull(repl.LastError);
RunReplication(repl);
// make sure doc1 is there
// TODO: make sure doc2 is there (refactoring needed)
var replicationUrlTrailing = new Uri(string.Format("{0}/", remote));
var pathToDoc = new Uri(replicationUrlTrailing, doc1Id);
Log.D(Tag, "Send http request to " + pathToDoc);
var httpRequestDoneSignal = new CountDownLatch(1);
var getDocTask = Task.Factory.StartNew(()=>
{
var httpclient = new HttpClient();
HttpResponseMessage response;
string responseString = null;
try
{
var responseTask = httpclient.GetAsync(pathToDoc.ToString());
responseTask.Wait(TimeSpan.FromSeconds(10));
response = responseTask.Result;
var statusLine = response.StatusCode;
NUnit.Framework.Assert.IsTrue(statusLine == HttpStatusCode.OK);
if (statusLine == HttpStatusCode.OK)
{
var responseStringTask = response.Content.ReadAsStringAsync();
responseStringTask.Wait(TimeSpan.FromSeconds(10));
responseString = responseStringTask.Result;
NUnit.Framework.Assert.IsTrue(responseString.Contains(doc1Id));
Log.D(ReplicationTest.Tag, "result: " + responseString);
}
else
{
var statusReason = response.ReasonPhrase;
response.Dispose();
throw new IOException(statusReason);
}
}
catch (ProtocolViolationException e)
{
NUnit.Framework.Assert.IsNull(e, "Got ClientProtocolException: " + e.Message);
}
catch (IOException e)
{
NUnit.Framework.Assert.IsNull(e, "Got IOException: " + e.Message);
}
httpRequestDoneSignal.CountDown();
});
//Closes the connection.
Log.D(Tag, "Waiting for http request to finish");
try
{
var result = httpRequestDoneSignal.Await(TimeSpan.FromSeconds(10));
Assert.IsTrue(result, "Could not retrieve the new doc from the sync gateway.");
Log.D(Tag, "http request finished");
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
Log.D(Tag, "testPusher() finished");
}
示例14: PushDocumentToSyncGateway
/// <exception cref="System.UriFormatException"></exception>
private void PushDocumentToSyncGateway(string docId, string docJson)
{
// push a document to server
Uri replicationUrlTrailingDoc1 = new Uri(string.Format("%s/%s", GetReplicationURL
().ToExternalForm(), docId));
Uri pathToDoc1 = new Uri(replicationUrlTrailingDoc1, docId);
Log.D(Tag, "Send http request to " + pathToDoc1);
CountDownLatch httpRequestDoneSignal = new CountDownLatch(1);
BackgroundTask getDocTask = new _BackgroundTask_139(pathToDoc1, docJson, httpRequestDoneSignal
);
getDocTask.Execute();
Log.D(Tag, "Waiting for http request to finish");
try
{
httpRequestDoneSignal.Await(300, TimeUnit.Seconds);
Log.D(Tag, "http request finished");
}
catch (Exception e)
{
Sharpen.Runtime.PrintStackTrace(e);
}
}
开发者ID:transformersprimeabcxyz,项目名称:_TO-DO-couchbase-lite-net-couchbase,代码行数:23,代码来源:Test7_PullReplication.cs
示例15: TestDocumentChangeListener
public void TestDocumentChangeListener() {
var doc = database.CreateDocument();
var counter = new CountDownLatch(1);
doc.Change += (sender, e) => counter.CountDown();
doc.CreateRevision().Save();
var success = counter.Await(TimeSpan.FromSeconds(5));
Assert.IsTrue(success);
}
开发者ID:transformersprimeabcxyz,项目名称:_TO-DO-couchbase-lite-net-couchbase,代码行数:10,代码来源:RevisionsTest.cs