private static HashData <T> GenerateHashData <T>(EqualsData <T> input) { Debug.Assert(input != null); var result = new HashData <T>(); foreach (T item in input.Items) { result.Add(item, item?.GetHashCode() ?? 0); } return(result); }
public IncludeCombinationTester() { var now = DateTime.UtcNow; var sources = new[] { "foo.js" }; var ic = new IncludeCombination(IncludeType.Js, sources, "alert('foo');", now, new JsTypeElement()); IdenticalCombinationsDifferentReferences = new EqualsData { A = ic, B = new IncludeCombination(IncludeType.Js, sources, "alert('foo');", now, new JsTypeElement()), AreEqual = true }; IdenticalCombinationsSameReferences = new EqualsData { A = ic, B = ic, AreEqual = true }; DifferentCombinations = new EqualsData { A = new IncludeCombination(IncludeType.Js, sources, "alert('foo');", now, new JsTypeElement()), B = new IncludeCombination(IncludeType.Css, new[] { "foo.css" }, "#foo{color:red;}", now, new CssTypeElement()), AreEqual = false }; NoCompression = new ResponseBodyBytes { Compression = ResponseCompression.None, Content = "alert('foo');", ExpectedBytes = new byte[] { 97, 108, 101, 114, 116, 40, 34, 102, 111, 111, 34, 41, 59 } }; Gzip = new ResponseBodyBytes { Compression = ResponseCompression.Gzip, Content = "alert('foo');", ExpectedBytes = new byte[] { 31, 139, 8, 0, 0, 0, 0, 0, 4, 0, 237, 189, 7, 96, 28, 73, 150, 37, 38, 47, 109, 202, 123, 127, 74, 245, 74, 215, 224, 116, 161, 8, 128, 96, 19, 36, 216, 144, 64, 16, 236, 193, 136, 205, 230, 146, 236, 29, 105, 71, 35, 41, 171, 42, 129, 202, 101, 86, 101, 93, 102, 22, 64, 204, 237, 157, 188, 247, 222, 123, 239, 189, 247, 222, 123, 239, 189, 247, 186, 59, 157, 78, 39, 247, 223, 255, 63, 92, 102, 100, 1, 108, 246, 206, 74, 218, 201, 158, 33, 128, 170, 200, 31, 63, 126, 124, 31, 63, 34, 178, 50, 175, 219, 173, 143, 206, 171, 234, 163, 59, 135, 255, 15, 79, 199, 134, 149, 13, 0, 0, 0 } }; Deflate = new ResponseBodyBytes { Compression = ResponseCompression.Deflate, Content = "alert('foo');", ExpectedBytes = new byte[] { 237, 189, 7, 96, 28, 73, 150, 37, 38, 47, 109, 202, 123, 127, 74, 245, 74, 215, 224, 116, 161, 8, 128, 96, 19, 36, 216, 144, 64, 16, 236, 193, 136, 205, 230, 146, 236, 29, 105, 71, 35, 41, 171, 42, 129, 202, 101, 86, 101, 93, 102, 22, 64, 204, 237, 157, 188, 247, 222, 123, 239, 189, 247, 222, 123, 239, 189, 247, 186, 59, 157, 78, 39, 247, 223, 255, 63, 92, 102, 100, 1, 108, 246, 206, 74, 218, 201, 158, 33, 128, 170, 200, 31, 63, 126, 124, 31, 63, 34, 178, 50, 175, 219, 173, 143, 206, 171, 234, 163, 59, 135, 255, 15 } }; }
public IncludeCombinationTester() { var now = DateTime.UtcNow; var sources = new[] { "foo.js" }; var ic = new IncludeCombination(IncludeType.Js, sources, "alert('foo');", now, new JsTypeElement()); IdenticalCombinationsDifferentReferences = new EqualsData { A = ic, B = new IncludeCombination(IncludeType.Js, sources, "alert('foo');", now, new JsTypeElement()), AreEqual = true }; IdenticalCombinationsSameReferences = new EqualsData { A = ic, B = ic, AreEqual = true }; DifferentCombinations = new EqualsData { A = new IncludeCombination(IncludeType.Js, sources, "alert('foo');", now, new JsTypeElement()), B = new IncludeCombination(IncludeType.Css, new[] { "foo.css" }, "#foo{color:red;}", now, new CssTypeElement()), AreEqual= false }; NoCompression = new ResponseBodyBytes { Compression = ResponseCompression.None, Content = "alert('foo');", ExpectedBytes = new byte[] { 97, 108, 101, 114, 116, 40, 34, 102, 111, 111, 34, 41, 59 } }; Gzip = new ResponseBodyBytes { Compression = ResponseCompression.Gzip, Content = "alert('foo');", ExpectedBytes = new byte[] { 31, 139, 8, 0, 0, 0, 0, 0, 4, 0, 237, 189, 7, 96, 28, 73, 150, 37, 38, 47, 109, 202, 123, 127, 74, 245, 74, 215, 224, 116, 161, 8, 128, 96, 19, 36, 216, 144, 64, 16, 236, 193, 136, 205, 230, 146, 236, 29, 105, 71, 35, 41, 171, 42, 129, 202, 101, 86, 101, 93, 102, 22, 64, 204, 237, 157, 188, 247, 222, 123, 239, 189, 247, 222, 123, 239, 189, 247, 186, 59, 157, 78, 39, 247, 223, 255, 63, 92, 102, 100, 1, 108, 246, 206, 74, 218, 201, 158, 33, 128, 170, 200, 31, 63, 126, 124, 31, 63, 34, 178, 50, 175, 219, 173, 143, 206, 171, 234, 163, 59, 135, 255, 15, 79, 199, 134, 149, 13, 0, 0, 0 } }; Deflate = new ResponseBodyBytes { Compression = ResponseCompression.Deflate, Content = "alert('foo');", ExpectedBytes = new byte[] { 237, 189, 7, 96, 28, 73, 150, 37, 38, 47, 109, 202, 123, 127, 74, 245, 74, 215, 224, 116, 161, 8, 128, 96, 19, 36, 216, 144, 64, 16, 236, 193, 136, 205, 230, 146, 236, 29, 105, 71, 35, 41, 171, 42, 129, 202, 101, 86, 101, 93, 102, 22, 64, 204, 237, 157, 188, 247, 222, 123, 239, 189, 247, 222, 123, 239, 189, 247, 186, 59, 157, 78, 39, 247, 223, 255, 63, 92, 102, 100, 1, 108, 246, 206, 74, 218, 201, 158, 33, 128, 170, 200, 31, 63, 126, 124, 31, 63, 34, 178, 50, 175, 219, 173, 143, 206, 171, 234, 163, 59, 135, 255, 15 } }; }
protected bool AnalyzeClause(Clause clause, object?before = null, object?after = null) { if (clause == null || (before == null && after == null)) { return(false); } try { // Support bare objects if (clause.Field is string) { after = GetValueByPropertyString(after, clause.Field); before = GetValueByPropertyString(before, clause.Field); } var typeHolder = before is null ? after : before; (var beforeList, var beforeDict) = ObjectToValues(before); (var afterList, var afterDict) = ObjectToValues(after); var valsToCheck = beforeList.Union(afterList); var dictToCheck = beforeDict.Union(afterDict); switch (clause.Operation) { case OPERATION.EQ: if (clause.Data is List <string> EqualsData) { if (EqualsData.Intersect(valsToCheck).Any()) { return(true); } } return(false); case OPERATION.NEQ: if (clause.Data is List <string> NotEqualsData) { if (!NotEqualsData.Intersect(valsToCheck).Any()) { return(true); } } return(false); // If *every* entry of the clause data is matched case OPERATION.CONTAINS: if (dictToCheck.Any()) { if (clause.DictData is List <KeyValuePair <string, string> > ContainsData) { if (ContainsData.All(y => dictToCheck.Any((x) => x.Key == y.Key && x.Value == y.Value))) { return(true); } } } else if (valsToCheck.Any()) { if (clause.Data is List <string> ContainsDataList) { // If we are dealing with an array on the object side if (typeHolder is List <string> ) { if (ContainsDataList.All(x => valsToCheck.Contains(x))) { return(true); } } // If we are dealing with a single string we do a .Contains instead else if (typeHolder is string) { if (clause.Data.All(x => valsToCheck.First()?.Contains(x) ?? false)) { return(true); } } } } return(false); // If *any* entry of the clause data is matched case OPERATION.CONTAINS_ANY: if (dictToCheck.Any()) { if (clause.DictData is List <KeyValuePair <string, string> > ContainsData) { foreach (KeyValuePair <string, string> value in ContainsData) { if (dictToCheck.Any(x => x.Key == value.Key && x.Value == value.Value)) { return(true); } } } } else if (valsToCheck.Any()) { if (clause.Data is List <string> ContainsDataList) { if (typeHolder is List <string> ) { if (ContainsDataList.Any(x => valsToCheck.Contains(x))) { return(true); } } // If we are dealing with a single string we do a .Contains instead else if (typeHolder is string) { if (clause.Data.Any(x => valsToCheck.First()?.Contains(x) ?? false)) { return(true); } } } } return(false); // If any of the data values are greater than the first provided clause value We // ignore all other clause values case OPERATION.GT: foreach (var val in valsToCheck) { if (int.TryParse(val, out int valToCheck)) { if (int.TryParse(clause.Data?[0], out int dataValue)) { if (valToCheck > dataValue) { return(true); } } } } return(false); // If any of the data values are less than the first provided clause value We // ignore all other clause values case OPERATION.LT: foreach (var val in valsToCheck) { if (int.TryParse(val, out int valToCheck)) { if (int.TryParse(clause.Data?[0], out int dataValue)) { if (valToCheck < dataValue) { return(true); } } } } return(false); // If any of the regexes match any of the values case OPERATION.REGEX: if (clause.Data is List <string> RegexList) { if (RegexList.Count > 0) { var built = string.Join('|', RegexList); if (!RegexCache.ContainsKey(built)) { try { RegexCache.TryAdd(built, new Regex(built, RegexOptions.Compiled)); } catch (ArgumentException) { Log.Warning("InvalidArgumentException when analyzing clause {0}. Regex {1} is invalid and will be skipped.", clause.Label, built); RegexCache.TryAdd(built, new Regex("", RegexOptions.Compiled)); } } if (valsToCheck.Any(x => RegexCache[built].IsMatch(x))) { return(true); } } } return(false); // Ignores provided data. Checks if the named property has changed. case OPERATION.WAS_MODIFIED: CompareLogic compareLogic = new CompareLogic(); ComparisonResult comparisonResult = compareLogic.Compare(before, after); return(!comparisonResult.AreEqual); // Ends with any of the provided data case OPERATION.ENDS_WITH: if (clause.Data is List <string> EndsWithData) { if (valsToCheck.Any(x => EndsWithData.Any(y => x is string && x.EndsWith(y, StringComparison.CurrentCulture)))) { return(true); } } return(false); // Starts with any of the provided data case OPERATION.STARTS_WITH: if (clause.Data is List <string> StartsWithData) { if (valsToCheck.Any(x => StartsWithData.Any(y => x is string && x.StartsWith(y, StringComparison.CurrentCulture)))) { return(true); } } return(false); case OPERATION.IS_NULL: if (valsToCheck.Count(x => x is null) == valsToCheck.Count()) { return(true); } return(false); case OPERATION.IS_TRUE: foreach (var valToCheck in valsToCheck) { if (bool.TryParse(valToCheck, out bool result)) { if (result) { return(true); } } } return(false); case OPERATION.IS_BEFORE: var valDateTimes = new List <DateTime>(); foreach (var valToCheck in valsToCheck) { if (DateTime.TryParse(valToCheck, out DateTime result)) { valDateTimes.Add(result); } } foreach (var data in clause.Data ?? new List <string>()) { if (DateTime.TryParse(data, out DateTime result)) { if (valDateTimes.Any(x => x.CompareTo(result) < 0)) { return(true); } } } return(false); case OPERATION.IS_AFTER: valDateTimes = new List <DateTime>(); foreach (var valToCheck in valsToCheck) { if (DateTime.TryParse(valToCheck, out DateTime result)) { valDateTimes.Add(result); } } foreach (var data in clause.Data ?? new List <string>()) { if (DateTime.TryParse(data, out DateTime result)) { if (valDateTimes.Any(x => x.CompareTo(result) > 0)) { return(true); } } } return(false); case OPERATION.IS_EXPIRED: foreach (var valToCheck in valsToCheck) { if (DateTime.TryParse(valToCheck, out DateTime result)) { if (result.CompareTo(DateTime.Now) < 0) { return(true); } } } return(false); case OPERATION.CONTAINS_KEY: return(dictToCheck.Any(x => clause.Data.Any(y => x.Key == y))); case OPERATION.CUSTOM: if (CustomOperationDelegate is null) { Log.Debug("Custom operation hit but {0} isn't set.", nameof(CustomOperationDelegate)); return(false); } else { return(CustomOperationDelegate.Invoke(clause, valsToCheck, dictToCheck)); } default: Log.Debug("Unimplemented operation {0}", clause.Operation); return(false); } } catch (Exception e) { Log.Debug(e, $"Hit while parsing {JsonConvert.SerializeObject(clause)} onto ({JsonConvert.SerializeObject(before)},{JsonConvert.SerializeObject(after)})"); } return(false); }
protected ANALYSIS_RESULT_TYPE Apply(Rule rule, CompareResult compareResult) { if (compareResult != null && rule != null) { var properties = _Properties[compareResult.ResultType]; foreach (Clause clause in rule.Clauses) { PropertyInfo property = properties.FirstOrDefault(iProp => iProp.Name.Equals(clause.Field)); if (property == null) { //Custom field logic will go here return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); } try { var valsToCheck = new List <string>(); List <KeyValuePair <string, string> > dictToCheck = new List <KeyValuePair <string, string> >(); if (property != null) { if (compareResult.ChangeType == CHANGE_TYPE.CREATED || compareResult.ChangeType == CHANGE_TYPE.MODIFIED) { try { if (GetValueByPropertyName(compareResult.Compare, property.Name) is List <string> ) { foreach (var value in (List <string>)(GetValueByPropertyName(compareResult.Compare, property.Name) ?? new List <string>())) { valsToCheck.Add(value); } } else if (GetValueByPropertyName(compareResult.Compare, property.Name) is Dictionary <string, string> ) { dictToCheck = ((Dictionary <string, string>)(GetValueByPropertyName(compareResult.Compare, property.Name) ?? new Dictionary <string, string>())).ToList(); } else if (GetValueByPropertyName(compareResult.Compare, property.Name) is List <KeyValuePair <string, string> > ) { dictToCheck = (List <KeyValuePair <string, string> >)(GetValueByPropertyName(compareResult.Compare, property.Name) ?? new List <KeyValuePair <string, string> >()); } else { var val = GetValueByPropertyName(compareResult.Compare, property.Name)?.ToString(); if (!string.IsNullOrEmpty(val)) { valsToCheck.Add(val); } } } catch (Exception e) { Log.Debug(e, "Error fetching Property {0} of Type {1}", property.Name, compareResult.ResultType); Log.Debug(Utf8Json.JsonSerializer.ToJsonString(compareResult)); Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>(); ExceptionEvent.Add("Exception Type", e.GetType().ToString()); AsaTelemetry.TrackEvent("ApplyCreatedModifiedException", ExceptionEvent); } } if (compareResult.ChangeType == CHANGE_TYPE.DELETED || compareResult.ChangeType == CHANGE_TYPE.MODIFIED) { try { if (GetValueByPropertyName(compareResult.Base, property.Name) is List <string> ) { foreach (var value in (List <string>)(GetValueByPropertyName(compareResult.Base, property.Name) ?? new List <string>())) { valsToCheck.Add(value); } } else if (GetValueByPropertyName(compareResult.Base, property.Name) is Dictionary <string, string> ) { dictToCheck = ((Dictionary <string, string>)(GetValueByPropertyName(compareResult.Base, property.Name) ?? new Dictionary <string, string>())).ToList(); } else if (GetValueByPropertyName(compareResult.Base, property.Name) is List <KeyValuePair <string, string> > ) { dictToCheck = (List <KeyValuePair <string, string> >)(GetValueByPropertyName(compareResult.Base, property.Name) ?? new List <KeyValuePair <string, string> >()); } else { var val = GetValueByPropertyName(compareResult.Base, property.Name)?.ToString(); if (!string.IsNullOrEmpty(val)) { valsToCheck.Add(val); } } } catch (Exception e) { Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>(); ExceptionEvent.Add("Exception Type", e.GetType().ToString()); AsaTelemetry.TrackEvent("ApplyDeletedModifiedException", ExceptionEvent); } } } switch (clause.Operation) { case OPERATION.EQ: if (clause.Data is List <string> EqualsData) { if (EqualsData.Intersect(valsToCheck).Any()) { break; } } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); case OPERATION.NEQ: if (clause.Data is List <string> NotEqualsData) { if (!NotEqualsData.Intersect(valsToCheck).Any()) { break; } } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // If *every* entry of the clause data is matched case OPERATION.CONTAINS: if (dictToCheck.Count > 0) { if (clause.DictData is List <KeyValuePair <string, string> > ContainsData) { if (ContainsData.Where(y => dictToCheck.Where((x) => x.Key == y.Key && x.Value == y.Value).Any()).Count() == ContainsData.Count) { break; } } } else if (valsToCheck.Count > 0) { if (clause.Data is List <string> ContainsDataList) { if (ContainsDataList.Intersect(valsToCheck).Count() == ContainsDataList.Count) { break; } } } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // If *any* entry of the clause data is matched case OPERATION.CONTAINS_ANY: if (dictToCheck.Count > 0) { if (clause.DictData is List <KeyValuePair <string, string> > ContainsData) { foreach (KeyValuePair <string, string> value in ContainsData) { if (dictToCheck.Where((x) => x.Key == value.Key && x.Value == value.Value).Any()) { break; } } } } else if (valsToCheck.Count > 0) { if (clause.Data is List <string> ContainsDataList) { if (clause.Data.Intersect(valsToCheck).Any()) { break; } } } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // If any of the clauses are not contained case OPERATION.DOES_NOT_CONTAIN: if (dictToCheck.Count > 0) { if (clause.DictData is List <KeyValuePair <string, string> > ContainsData) { if (ContainsData.Where(y => dictToCheck.Where((x) => x.Key == y.Key && x.Value == y.Value).Any()).Any()) { break; } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); } } else if (valsToCheck.Count > 0) { if (clause.Data is List <string> ContainsDataList) { if (ContainsDataList.Intersect(valsToCheck).Any()) { break; } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); } } break; // If any of the data values are greater than the first provided data value case OPERATION.GT: if (valsToCheck.Where(val => (int.Parse(val, CultureInfo.InvariantCulture) > int.Parse(clause.Data?[0] ?? $"{int.MinValue}", CultureInfo.InvariantCulture))).Any()) { break; } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // If any of the data values are less than the first provided data value case OPERATION.LT: if (valsToCheck.Where(val => (int.Parse(val, CultureInfo.InvariantCulture) < int.Parse(clause.Data?[0] ?? $"{int.MaxValue}", CultureInfo.InvariantCulture))).Any()) { break; } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // If any of the regexes match any of the values case OPERATION.REGEX: if (clause.Data is List <string> RegexList) { var regexList = RegexList.Select(x => new Regex(x)); if (valsToCheck.Where(x => regexList.Where(y => y.IsMatch(x)).Any()).Any()) { break; } } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // Ignores provided data. Checks if the named property has changed. case OPERATION.WAS_MODIFIED: if ((valsToCheck.Count == 2) && (valsToCheck[0] == valsToCheck[1])) { break; } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // Ends with any of the provided data case OPERATION.ENDS_WITH: if (clause.Data is List <string> EndsWithData) { if (valsToCheck.Where(x => EndsWithData.Where(y => x.EndsWith(y, StringComparison.CurrentCulture)).Any()).Any()) { break; } } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); // Starts with any of the provided data case OPERATION.STARTS_WITH: if (clause.Data is List <string> StartsWithData) { if (valsToCheck.Where(x => StartsWithData.Where(y => x.StartsWith(y, StringComparison.CurrentCulture)).Any()).Any()) { break; } } return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); default: Log.Debug("Unimplemented operation {0}", clause.Operation); return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); } } catch (Exception e) { Log.Debug(e, $"Hit while parsing {JsonSerializer.Serialize(rule)} onto {JsonSerializer.Serialize(compareResult)}"); Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>(); ExceptionEvent.Add("Exception Type", e.GetType().ToString()); AsaTelemetry.TrackEvent("ApplyOverallException", ExceptionEvent); return(DEFAULT_RESULT_TYPE_MAP[compareResult.ResultType]); } } compareResult.Rules.Add(rule); return(rule.Flag); } else { throw new NullReferenceException(); } }
public void Equals_CorrectlyComparesTwoCombinations(EqualsData ed) { var result = ed.A.Equals(ed.B); Assert.AreEqual(ed.AreEqual, result); }
public void Equals_CorrectlyComparesObjectToCombination(EqualsData ed) { var result = ((object)ed.A).Equals(ed.B); Assert.AreEqual(ed.AreEqual, result); }
public void Equals_CorrectlyComparesCombinationToObject(EqualsData ed) { var result = ed.A.Equals((object)ed.B); Assert.AreEqual(ed.AreEqual, result); }