Example #1
0
        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);
            }
        }
Example #2
0
        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]);
            }
        }
Example #3
0
        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();
                }
            }
        }
Example #4
0
        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);"
                });
            }
        }
Example #5
0
        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"));
            }
        }
Example #6
0
        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"
                    });
                }
            });
        }
Example #7
0
        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"));
            }
        }
Example #8
0
        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);
        }
Example #9
0
        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]);
            }
        }
Example #10
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>(), "*****@*****.**");
            }
        }
Example #11
0
        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);
            }
        }
Example #12
0
        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"));
            }
        }
Example #14
0
        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);
        }
Example #15
0
        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();
                }
            }
        }
Example #16
0
        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);
            }
        }
Example #17
0
        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);
            }
        }
Example #18
0
        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"]);
            }
        }
Example #19
0
        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>()));
            }
        }
Example #20
0
        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");
            }
        }
Example #21
0
        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);
            }
        }
Example #22
0
        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"]);
            }
        }
Example #23
0
        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]);
            }
        }
Example #24
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);
        }
Example #25
0
        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));
        }