public void CanUseToISOString() { var date = DateTime.UtcNow; var dateOffset = DateTime.Now.AddMilliseconds(100); var testObject = new CustomType { Date = date, DateOffset = dateOffset }; var doc = RavenJObject.FromObject(testObject); var patch = new ScriptedPatchRequest() { Script = @" this.DateOutput = new Date(this.Date).toISOString(); this.DateOffsetOutput = new Date(this.DateOffset).toISOString(); " }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var scriptedJsonPatcher = new ScriptedJsonPatcher(); var result = scriptedJsonPatcher.Apply(scope, doc, patch); var dateOutput = result.Value <string>("DateOutput"); var dateOffsetOutput = result.Value <string>("DateOffsetOutput"); // With the custom fixes to Jint, these tests now pass (RavenDB-1536) Assert.Equal(date.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), dateOutput); Assert.Equal(dateOffset.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), dateOffsetOutput); } }
public void PatcherCanOutputObjectsCorrectly() { var doc = RavenJObject.Parse("{}"); const string script = @"output(undefined); output(true); output(2); output(2.5); output('string'); output(null); output([2, 'c']); output({'a': 'c', 'f': { 'x' : 2}});" ; var patch = new ScriptedPatchRequest() { Script = script }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var patcher = new ScriptedJsonPatcher(); patcher.Apply(scope, doc, patch); Assert.Equal(8, patcher.Debug.Count); Assert.Equal("undefined", patcher.Debug[0]); Assert.Equal("True", patcher.Debug[1]); Assert.Equal("2", patcher.Debug[2]); Assert.Equal("2.5", patcher.Debug[3]); Assert.Equal("string", patcher.Debug[4]); Assert.Equal("null", patcher.Debug[5]); Assert.Equal("[2,\"c\"]", patcher.Debug[6]); Assert.Equal("{\"a\":\"c\",\"f\":{\"x\":2}}", patcher.Debug[7]); } }
public Tuple <PatchResultData, List <string> > ApplyPatch(string docId, Etag etag, ScriptedPatchRequest patchExisting, ScriptedPatchRequest patchDefault, RavenJObject defaultMetadata, TransactionInformation transactionInformation, bool debugMode = false, IEnumerable <string> participatingIds = null) { ScriptedJsonPatcher scriptedJsonPatcher = null; DefaultScriptedJsonPatcherOperationScope scope = null; try { var applyPatchInternal = ApplyPatchInternal(docId, etag, transactionInformation, jsonDoc => { scope = scope ?? new DefaultScriptedJsonPatcherOperationScope(Database, debugMode); scriptedJsonPatcher = new ScriptedJsonPatcher(Database); return(scriptedJsonPatcher.Apply(scope, jsonDoc.ToJson(), patchExisting, jsonDoc.SerializedSizeOnDisk, jsonDoc.Key)); }, () => { if (patchDefault == null) { return(null); } scope = scope ?? new DefaultScriptedJsonPatcherOperationScope(Database, debugMode); scriptedJsonPatcher = new ScriptedJsonPatcher(Database); var jsonDoc = new RavenJObject(); jsonDoc[Constants.Metadata] = defaultMetadata.CloneToken() ?? new RavenJObject(); return(scriptedJsonPatcher.Apply(scope, jsonDoc, patchDefault, 0, docId)); }, () => { if (scope == null) { return(null); } return(scope .GetPutOperations() .ToList()); }, () => { if (scope == null) { return(null); } return(scope.DebugActions); }, debugMode, participatingIds: participatingIds); return(Tuple.Create(applyPatchInternal, scriptedJsonPatcher == null ? new List <string>() : scriptedJsonPatcher.Debug)); } finally { if (scope != null) { scope.Dispose(); } } }
public void CanProcess() { var document = new RavenJObject { { "Data", new RavenJObject { { "Title", "Hi" } } } }; const string name = @"Raven.Tests.Patching.x2js.js"; var manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name); var code = new StreamReader(manifestResourceStream).ReadToEnd(); var jsonPatcher = new ScriptedJsonPatcher(); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { scope.CustomFunctions = new JsonDocument { DataAsJson = new RavenJObject { { "Functions", code } } }; jsonPatcher.Apply(scope, document, new ScriptedPatchRequest { Script = "this.Xml = js2x(this.Data);" }); } }
public void NullStringPropertiesShouldBeConvertedProperly() { using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var engine = new Engine(); var jsObject = engine.Object.Construct(Arguments.Empty); jsObject.Put("Test", new JsValue((string)null), true); var result = scope.ToRavenJObject(jsObject); Assert.Null(result.Value <string>("Test")); } }
public void CanHandleNonsensePatching() { var doc = RavenJObject.FromObject(test); Assert.Throws <ParseException>(() => { using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { new ScriptedJsonPatcher().Apply(scope, doc, new ScriptedPatchRequest { Script = "this.Id = 'Something" }); } }); }
public void CanPatchUsingVars() { var doc = RavenJObject.FromObject(test); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var resultJson = new ScriptedJsonPatcher().Apply(scope, doc, new ScriptedPatchRequest { Script = "this.TheName = Name", Values = { { "Name", "ayende" } } }); Assert.Equal("ayende", resultJson.Value <string>("TheName")); } }
public void CanThrowIfValueIsWrong() { var doc = RavenJObject.FromObject(test); var invalidOperationException = Assert.Throws <InvalidOperationException>(() => { using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { new ScriptedJsonPatcher().Apply(scope, doc, new ScriptedPatchRequest { Script = "throw 'problem'" }); } }); Assert.Contains("problem", invalidOperationException.Message); }
public void CanOutputDebugInformation() { var doc = RavenJObject.FromObject(test); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var advancedJsonPatcher = new ScriptedJsonPatcher(); advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest { Script = "output(this.Id)" }); Assert.Equal("someId", advancedJsonPatcher.Debug[0]); } }
public void CanUseTrim() { var doc = RavenJObject.Parse("{\"Email\":' [email protected] '}"); const string script = "this.Email = this.Email.trim();"; var patch = new ScriptedPatchRequest() { Script = script, }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var result = new ScriptedJsonPatcher().Apply(scope, doc, patch); Assert.Equal(result["Email"].Value <string>(), "*****@*****.**"); } }
public void CanUseMathFloor() { var doc = RavenJObject.Parse("{\"Email\":' [email protected] '}"); const string script = "this.Age = Math.floor(1.6);"; var patch = new ScriptedPatchRequest() { Script = script, }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var result = new ScriptedJsonPatcher().Apply(scope, doc, patch); Assert.Equal(result["Age"].Value <int>(), 1); } }
public void Manual() { var doc = RavenJObject.FromObject(new Product { Tags = new string[0], }); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var resultJson = new ScriptedJsonPatcher().Apply(scope, doc, new ScriptedPatchRequest { Script = "this.Tags2 = this.Tags.Map(function(value) { return value; });", }); Assert.Equal(0, resultJson.Value <RavenJArray>("Tags2").Length); } }
public void ShouldWork() { var scriptedJsonPatcher = new ScriptedJsonPatcher(); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var result = scriptedJsonPatcher.Apply(scope, new RavenJObject { { "Val", double.NaN } }, new ScriptedPatchRequest { Script = @"this.Finite = isFinite(this.Val);" }); Assert.False(result.Value <bool>("Finite")); } }
public void CreateDocumentShouldThrowInvalidEtagException() { var doc = RavenJObject.FromObject(test); var advancedJsonPatcher = new ScriptedJsonPatcher(); var x = Assert.Throws <InvalidOperationException>(() => { using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest { Script = @"PutDocument('Items/1', { Property: 1}, {'@etag': 'invalid-etag' });" }); } }); Assert.Contains("Invalid ETag value 'invalid-etag' for document 'Items/1'", x.InnerException.Message); }
public Tuple <PatchResultData, List <string> > ApplyPatch(string docId, Etag etag, ScriptedPatchRequest patch, TransactionInformation transactionInformation, bool debugMode = false) { ScriptedJsonPatcher scriptedJsonPatcher = null; DefaultScriptedJsonPatcherOperationScope scope = null; try { var applyPatchInternal = ApplyPatchInternal(docId, etag, transactionInformation, jsonDoc => { scope = new DefaultScriptedJsonPatcherOperationScope(Database, debugMode); scriptedJsonPatcher = new ScriptedJsonPatcher(Database); return(scriptedJsonPatcher.Apply(scope, jsonDoc.ToJson(), patch, jsonDoc.SerializedSizeOnDisk, jsonDoc.Key)); }, () => null, () => { if (scope == null) { return(null); } return(scope .GetPutOperations() .ToList()); }, () => { if (scope == null) { return(null); } return(scope.DebugActions); }, debugMode); return(Tuple.Create(applyPatchInternal, scriptedJsonPatcher == null ? new List <string>() : scriptedJsonPatcher.Debug)); } finally { if (scope != null) { scope.Dispose(); } } }
public void CanRemoveFromCollectionByValue() { var doc = RavenJObject.FromObject(test); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var resultJson = new ScriptedJsonPatcher().Apply(scope, doc, new ScriptedPatchRequest { Script = @" this.Comments.Remove('two'); " }); var result = JsonConvert.DeserializeObject <CustomType>(resultJson.ToString()); Assert.Equal(new[] { "one", "seven" }.ToList(), result.Comments); } }
public void ComplexVariableTest() { const string email = "*****@*****.**"; var doc = RavenJObject.Parse("{\"Email\":null}"); const string script = "this.Email = data.Email;"; var patch = new ScriptedPatchRequest() { Script = script, Values = { { "data", new { Email = email } } } }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var result = new ScriptedJsonPatcher().Apply(scope, doc, patch); Assert.Equal(result["Email"].Value <string>(), email); } }
public void ComplexVariableTest2() { const string email = "*****@*****.**"; var doc = RavenJObject.Parse("{\"Contact\":null}"); const string script = "this.Contact = contact.Email;"; var patch = new ScriptedPatchRequest() { Script = script, Values = { { "contact", new { Email = email } } } }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var result = new ScriptedJsonPatcher().Apply(scope, doc, patch); Assert.NotNull(result["Contact"]); } }
public void CanUseLoDash() { const string email = "*****@*****.**"; var doc = RavenJObject.Parse("{\"Contact\":null}"); const string script = "this.Emails = _.times(3, function(i) { return contact.Email + i; });"; var patch = new ScriptedPatchRequest() { Script = script, Values = { { "contact", new { Email = email } } } }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var result = new ScriptedJsonPatcher().Apply(scope, doc, patch); Assert.Equal(new[] { "[email protected]", "[email protected]", "[email protected]" }, result.Value <RavenJArray>("Emails").Select(x => x.Value <string>())); } }
public void CanUseSplit() { var doc = RavenJObject.Parse("{\"Email\":'*****@*****.**'}"); const string script = @" this.Parts = this.Email.split('@');"; var patch = new ScriptedPatchRequest() { Script = script, }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var scriptedJsonPatcher = new ScriptedJsonPatcher(); var result = scriptedJsonPatcher.Apply(scope, doc, patch); Assert.Equal(result["Parts"].Value <RavenJArray>()[0], "somebody"); Assert.Equal(result["Parts"].Value <RavenJArray>()[1], "somewhere.com"); } }
public void CanRemoveFromCollectionByCondition() { var doc = RavenJObject.FromObject(test); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var advancedJsonPatcher = new ScriptedJsonPatcher(); var resultJson = advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest { Script = @" this.Comments.RemoveWhere(function(el) {return el == 'seven';}); " }); var result = JsonConvert.DeserializeObject <CustomType>(resultJson.ToString()); Assert.Equal(new[] { "one", "two" }.ToList(), result.Comments); } }
public void CanApplyBasicScriptAsPatch() { var doc = RavenJObject.FromObject(test); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var resultJson = new ScriptedJsonPatcher().Apply(scope, doc, new ScriptedPatchRequest { Script = sampleScript }); var result = JsonConvert.DeserializeObject <CustomType>(resultJson.ToString()); Assert.Equal("Something new", result.Id); Assert.Equal(2, result.Comments.Count); Assert.Equal("one test", result.Comments[0]); Assert.Equal("two", result.Comments[1]); Assert.Equal(12144, result.Value); Assert.Equal("err!!", resultJson["newValue"]); } }
public void CanPatchUsingRavenJObjectVars() { var doc = RavenJObject.FromObject(test); var variableSource = new { NewComment = "New Comment" }; var variable = RavenJObject.FromObject(variableSource); var script = "this.Comments[0] = variable.NewComment;"; var patch = new ScriptedPatchRequest() { Script = script, Values = { { "variable", variable } } }; using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var resultJson = new ScriptedJsonPatcher().Apply(scope, doc, patch); var result = JsonConvert.DeserializeObject <CustomType>(resultJson.ToString()); Assert.Equal(variableSource.NewComment, result.Comments[0]); } }
public void CannotUseInfiniteLoop() { var doc = RavenJObject.FromObject(test); var advancedJsonPatcher = new ScriptedJsonPatcher(); var x = Assert.Throws <InvalidOperationException>(() => { using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest { Script = "while(true) {}" }); } }); Assert.Contains("Unable to execute JavaScript", x.Message); var inner = x.InnerException as StatementsCountOverflowException; Assert.NotNull(inner); Assert.Equal("The maximum number of statements executed have been reached.", inner.Message); }
public void CreateDocumentShouldThrowIfSpecifiedJsonIsNullOrEmptyString() { var doc = RavenJObject.FromObject(test); var advancedJsonPatcher = new ScriptedJsonPatcher(); using (var scope = new DefaultScriptedJsonPatcherOperationScope()) { var x = Assert.Throws <InvalidOperationException>(() => advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest { Script = @"PutDocument('Items/1', null);" })); Assert.Contains("Created document cannot be null or empty. Document key: 'Items/1'", x.InnerException.Message); x = Assert.Throws <InvalidOperationException>(() => advancedJsonPatcher.Apply(scope, doc, new ScriptedPatchRequest { Script = @"PutDocument('Items/1', null, null);" })); Assert.Contains("Created document cannot be null or empty. Document key: 'Items/1'", x.InnerException.Message); } }
private bool WillReplicateByScript(string script, JsonDocument document) { var scriptedPatchRequest = new ScriptedPatchRequest { Script = script }; var patcher = new ReplicationScriptedJsonPatcher(database, scriptedPatchRequest); using (var scope = new DefaultScriptedJsonPatcherOperationScope(database)) { try { patcher.Apply(scope, document.ToJson(), scriptedPatchRequest, document.SerializedSizeOnDisk); //null means that we should skip this document return(scope.ActualPatchResult != JsValue.Null); } catch (Exception e) { //this document will not be replicated return(false); } } }
public IEnumerable <JsonDocument> Handle(IEnumerable <JsonDocument> docs) { if (strategy.SpecifiedCollections == null || strategy.SpecifiedCollections.Count == 0) { return(docs); } return(docs.Select(doc => { var collection = doc.Metadata.Value <string>(Constants.RavenEntityName); string script; if (string.IsNullOrEmpty(collection) || strategy.SpecifiedCollections.TryGetValue(collection, out script) == false) { if (Log.IsDebugEnabled) { Log.Debug(string.Format("Will not replicate document '{0}' to '{1}' because the replication of specified collection is turned on while the document does not belong to any of them", doc.Key, destinationId)); } return null; } if (script == null) { return doc; } var scriptedPatchRequest = new ScriptedPatchRequest { Script = script }; var patcher = new ReplicationScriptedJsonPatcher(database, scriptedPatchRequest); using (var scope = new DefaultScriptedJsonPatcherOperationScope(database)) { try { var transformedDoc = patcher.Apply(scope, doc.ToJson(), scriptedPatchRequest, doc.SerializedSizeOnDisk); if (scope.ActualPatchResult == JsValue.Null) // null means that document should be skip { if (Log.IsDebugEnabled) { Log.Debug(string.Format("Will not replicate document '{0}' to '{1}' because a collection specific script filtered it out", doc.Key, destinationId)); } return null; } doc.Metadata = (RavenJObject)transformedDoc[Constants.Metadata]; transformedDoc.Remove(Constants.Metadata); doc.DataAsJson = transformedDoc; return doc; } catch (ParseException e) { Log.WarnException(string.Format("Could not parse replication transformation script of '{0}' collection on document {1}", collection, doc.Key), e); throw; } catch (Exception e) { Log.WarnException(string.Format("Could not apply replication transformation script of '{0}' collection on document {1}", collection, doc.Key), e); throw; } } }) .Where(x => x != null)); }