//-----------------------------------------------------------------------------
//
// Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// A copy of the License is located at
//
// http://aws.amazon.com/apache2.0
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
//
//-----------------------------------------------------------------------------
using Amazon.XRay.Recorder.Core.Sampling;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
namespace Amazon.XRay.Recorder.UnitTests
{
[TestClass]
public class RuleCacheTests : TestBase
{
[TestMethod]
public void TestLoadRules1() // Test basic LoadRules
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingRule rule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, "test", "test", "GET", "/api/5");
newRules.Add(rule);
ruleCache.LoadRules(newRules);
IList rulesInCache = ruleCache.GetRules();
Assert.AreEqual(1,rulesInCache.Count);
}
[TestMethod]
public void TestLoadRulesSort() // Test whether cache is sorted after LoadRules by priority and then by ruleName
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingRule rule1 = RuleCacheTests.GetSamplingRule("a", 2);
SamplingRule rule2 = RuleCacheTests.GetSamplingRule("b", 1);
SamplingRule rule3 = RuleCacheTests.GetSamplingRule("c", 3);
SamplingRule rule4 = RuleCacheTests.GetSamplingRule("d", 3);
newRules.Add(rule1);
newRules.Add(rule2);
newRules.Add(rule3);
newRules.Add(rule4);
ruleCache.LoadRules(newRules);
IList rulesInCache = ruleCache.GetRules();
Assert.AreEqual(4, rulesInCache.Count);
Assert.AreEqual(rule2.RuleName, rulesInCache[0].RuleName);
Assert.AreEqual(rule1.RuleName, rulesInCache[1].RuleName);
Assert.AreEqual(rule3.RuleName, rulesInCache[2].RuleName);
Assert.AreEqual(rule4.RuleName, rulesInCache[3].RuleName);
}
[TestMethod]
public void TestLoadTargets() // Test statefule attributes of already present rule in cache is carried to new rules.
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingRule rule1 = RuleCacheTests.GetSamplingRule("a", 2);
SamplingRule rule2 = RuleCacheTests.GetSamplingRule("b", 1);
newRules.Add(rule1);
newRules.Add(rule2);
ruleCache.LoadRules(newRules);
IList rulesInCache = ruleCache.GetRules();
Assert.AreEqual(2, rulesInCache.Count);
Assert.AreEqual(rule2.RuleName, rulesInCache[0].RuleName);
Assert.AreEqual(rule1.RuleName, rulesInCache[1].RuleName);
// Load Targets
DateTime dateTime = TimeStamp.CurrentDateTime();
TimeStamp currentTime = new TimeStamp(dateTime);
Target t1 = new Target("a", 0.9, 10, dateTime, 10);
Target t2 = new Target("b", 0.5, 10, dateTime, 10);
List newTargets = new List();
newTargets.Add(t1);
newTargets.Add(t2);
ruleCache.LoadTargets(newTargets);
rulesInCache = ruleCache.GetRules(); // check targets value is copied
Reservior actualReservior2 = rulesInCache[0].Reservior;
Assert.AreEqual(currentTime.Time, actualReservior2.TTL.Time);
Assert.AreEqual(t2.Interval, actualReservior2.Interval);
Assert.AreEqual(t2.ReserviorQuota, actualReservior2.Quota);
Reservior actualReservior1 = rulesInCache[1].Reservior;
Assert.AreEqual(currentTime.Time, actualReservior1.TTL.Time);
Assert.AreEqual(t1.Interval, actualReservior1.Interval);
Assert.AreEqual(t1.ReserviorQuota, actualReservior1.Quota);
}
[TestMethod]
public void TestMerge() // Test statefule attributes of already present rule in cache is carried to new rules.
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingRule rule1 = RuleCacheTests.GetSamplingRule("a", 2);
Statistics expectedStatistic = new Statistics(2, 1, 1);
rule1.Statistics = expectedStatistic;
SamplingRule rule2 = RuleCacheTests.GetSamplingRule("b", 1);
newRules.Add(rule1);
newRules.Add(rule2);
ruleCache.LoadRules(newRules);
IList rulesInCache = ruleCache.GetRules();
Assert.AreEqual(2, rulesInCache.Count);
Assert.AreEqual(rule2.RuleName, rulesInCache[0].RuleName);
Assert.AreEqual(rule1.RuleName, rulesInCache[1].RuleName);
// Load Targets
DateTime dateTime = TimeStamp.CurrentDateTime();
TimeStamp currentTime = new TimeStamp(dateTime);
Target t1 = new Target("a", 0.9, 10, dateTime, 10);
Target t2 = new Target("b", 0.5, 10, dateTime, 10);
List newTargets = new List();
newTargets.Add(t1);
newTargets.Add(t2);
ruleCache.LoadTargets(newTargets);
_ = ruleCache.GetRules();
rule1 = RuleCacheTests.GetSamplingRule("a", 1);
newRules = new List();
newRules.Add(rule1);
ruleCache.LoadRules(newRules); // In the next iteration, rule a with update prioirty and rule b is deleted.
rulesInCache = ruleCache.GetRules();
Assert.AreEqual(1, rulesInCache.Count); // only one rule should be present and statefule info should be carried from old rule
Assert.AreEqual(1, rulesInCache[0].Priority); // implies new rule is added to cache
Reservior actualReservior1 = rulesInCache[0].Reservior;
Assert.AreEqual(currentTime.Time, actualReservior1.TTL.Time);
Assert.AreEqual(t1.Interval, actualReservior1.Interval);
Assert.AreEqual(t1.ReserviorQuota, actualReservior1.Quota);
Statistics statistics = rulesInCache[0].Statistics;
Assert.AreEqual(expectedStatistic.RequestCount, statistics.RequestCount);
Assert.AreEqual(expectedStatistic.BorrowCount, statistics.BorrowCount);
Assert.AreEqual(expectedStatistic.SampledCount, statistics.SampledCount);
}
[TestMethod]
public void TestGetMatchedRule1() // Test basic matching rule
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "AWS::ECS::Container");
SamplingRule expectedRule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, samplingInput.Host, samplingInput.ServiceName, samplingInput.Method, samplingInput.Url, serviceType: samplingInput.ServiceType);
newRules.Add(expectedRule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput,current);
Assert.IsTrue(actualRule.Equals(expectedRule));
}
[TestMethod]
public void TestGetMatchedRule2() // ServiceType is different
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "AWS::ECS::Container");
SamplingRule expectedRule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, samplingInput.Host, samplingInput.ServiceName, samplingInput.Method, samplingInput.Url, serviceType:"XYZ");
newRules.Add(expectedRule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current);
Assert.IsNull(actualRule);
}
[TestMethod]
public void TestGetMatchedRule3() // sampling input ServiceName and ServiceType is null - it should be ignored for rule matching
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "", "");
SamplingRule expectedRule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, samplingInput.Host, "test", samplingInput.Method, samplingInput.Url, serviceType: "XYZ");
newRules.Add(expectedRule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current);
Assert.IsTrue(actualRule.Equals(expectedRule));
}
[TestMethod]
public void TestGetMatchedRule4() // sampling input has only ServiceName - the rule should be matched
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk");
SamplingRule expectedRule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, serviceName: samplingInput.ServiceName);
newRules.Add(expectedRule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current);
Assert.IsTrue(actualRule.Equals(expectedRule));
}
[TestMethod]
public void TestGetMatchedRuleNotMatching() // Rule not matched
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
SamplingRule rule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, "j", samplingInput.ServiceName, samplingInput.Method, samplingInput.Url);
newRules.Add(rule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current);
Assert.IsNull(actualRule);
}
[TestMethod]
public void TestGetMatchedRuleNotMatching2() // SamplingInput with only ServiceName - Rule not matched
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk");
SamplingRule rule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, serviceName: "XYZ");
newRules.Add(rule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current);
Assert.IsNull(actualRule);
}
[TestMethod]
public void TestGetMatchedRuleWithDefaultRule() // Matching with default Rule;
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
SamplingRule rule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, "j", "test", samplingInput.Method, samplingInput.Url);
newRules.Add(rule);
SamplingRule expectedRule = RuleCacheTests.GetSamplingRule(SamplingRule.Default, 10000, 0.5, 1, "j", "*", "*","*"); // should match to default rule
newRules.Add(expectedRule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current);
Assert.IsTrue(actualRule.Equals(expectedRule));
}
[TestMethod]
public void TestGetMatchedRuleWithDefaultRule2() // SamplingInput with only ServiceName - Matching with default Rule;
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk");
SamplingRule rule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, serviceName: "XYZ");
newRules.Add(rule);
SamplingRule expectedRule = RuleCacheTests.GetSamplingRule(SamplingRule.Default, 10000, 0.5, 1, "j", "*", "*", "*"); // should match to default rule
newRules.Add(expectedRule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated = current;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current);
Assert.IsTrue(actualRule.Equals(expectedRule));
}
[TestMethod]
public void TestGetMatchedRuleForExpiredCache1() // Cache not loaded, hould return null
{
RuleCache ruleCache = new RuleCache();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
TimeStamp current = TimeStamp.CurrentTime();
var actualRule = ruleCache.GetMatchedRule(samplingInput, current); // cache is expired since never loaded
Assert.IsNull(actualRule);
}
[TestMethod]
public void TestGetMatchedRuleForExpiredCache2() // Expired cache should not match rule.
{
RuleCache ruleCache = new RuleCache();
List newRules = new List();
SamplingInput samplingInput = new SamplingInput("elasticbeanstalk", "/api/1", "GET", "dynamo", "*");
SamplingRule expectedRule = RuleCacheTests.GetSamplingRule("a", 1, 0.5, 10, samplingInput.Host, samplingInput.ServiceName, samplingInput.Method, samplingInput.Url);
newRules.Add(expectedRule);
ruleCache.LoadRules(newRules);
TimeStamp current = TimeStamp.CurrentTime();
ruleCache.LastUpdated.Time = current.Time;
current.Time += RuleCache.TTL + 1;
var actualRule = ruleCache.GetMatchedRule(samplingInput, current); // cache is expired, though matching rule is present
Assert.IsNull(actualRule);
}
private static SamplingRule GetSamplingRule(string ruleName, int priority, double fixedRate = 0, int reservoirSize = 0, string host = null, string serviceName = null, string httpMethod = null, string urlPath = null, string serviceType = "*", string resourceARN = "*", Dictionary attributes = null)
{
return new SamplingRule(ruleName,priority,fixedRate,reservoirSize,host,serviceName,httpMethod,urlPath,serviceType,resourceARN,attributes);
}
}
}