//----------------------------------------------------------------------------- // // 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 System; using System.Globalization; using System.IO; using System.Linq; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using Amazon.XRay.Recorder.Core.Exceptions; using Amazon.XRay.Recorder.Core.Internal.Entities; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Amazon.XRay.Recorder.UnitTests { [TestClass] public class SegmentTests : TestBase { private string[] _validTraceIds = new string[] { "1-5759e988-bd862e3fe1be46a994272793", "1-5759E988-BD862E3FE1BE46A994272793" }; private string[] _invalidTraceIds = new string[] { string.Empty, "2-5759e988-bd862e3fe1be46a994272793", "1-5759e988a-bd862e3fe1be46a99427279", "1-5759e988-bd862e3fe1be46a994272793a", "1-5759e988-bd862e3fe1be46a99427khkj", "1-xxxxxxxx-bd862e3fe1be46a994272793", "a-5759e988-bd862e3fe1be46a994272793", "1*5759e988,bd862e3fe1be46a994272793", "1-5759e9881111-bd862e3fe1be46a99427", "1-5759e-bd862e3fe1be46a994272111793", "1-HJKLEIUR-bd862e3fe1be46a994272793", "1-.759e988-bd862e3fe1be46a994272793" }; private string[] _invalidSegmentIds = new string[] { string.Empty, "123", "1234567890", "abcdefgh", ",./!@#$%" }; [TestMethod] public void TestCreateSubsegmentWithName() { var subsegment = new Subsegment("test"); Assert.AreEqual(subsegment.Name, "test"); Assert.IsTrue(Entity.IsIdValid(subsegment.Id)); Assert.IsNull(subsegment.TraceId); Assert.IsNull(subsegment.ParentId); Assert.IsFalse(subsegment.IsSubsegmentsAdded); } [TestMethod] public void TestCreateSegmentWithInvalidParentId() { foreach (string id in _invalidSegmentIds) { try { var segment = new Segment("test", null, id); Assert.Fail(); } catch (ArgumentException) { } } } [TestMethod] public void TestCreateSegmentWithValidTraceId() { try { foreach (string id in _validTraceIds) { var segment = new Segment("test", id); } } catch (ArgumentException ex) { Assert.Fail("Expected no exception, but got: " + ex.Message); } } [TestMethod] public void TestCreateSegmentWithInvalidTraceId() { foreach (string id in _invalidTraceIds) { try { var segment = new Segment(id, "test"); // If an exception is not thrown with invalid id, fail the test Assert.Fail(); } catch (ArgumentException) { continue; } } } [TestMethod] [ExpectedException(typeof(ArgumentNullException))] public void CreateSegmentWithInvalidNameTest() { _ = new Segment(null, TraceId); } [TestMethod] public void TestSegmentIdIsValid() { var segment = new Segment("test", _validTraceIds[0]); string id = segment.Id; Assert.AreEqual(id.Length, 16); Assert.IsTrue(long.TryParse(id, NumberStyles.HexNumber, null, out _)); } [TestMethod] public void TestAddSegment() { var parent = new Segment("parent", TraceId); var child = new Subsegment("child"); parent.AddSubsegment(child); Assert.ReferenceEquals(child.Parent, parent); Assert.IsTrue(parent.Subsegments.Contains(child)); } [TestMethod] public void TestReferenceCountWithOneSegment() { var segment = new Segment("test", TraceId); Assert.AreEqual(segment.Reference, 1); Assert.IsFalse(segment.IsEmittable()); segment.Release(); Assert.AreEqual(segment.Reference, 0); Assert.IsTrue(segment.IsEmittable()); } [TestMethod] public void TestAddRefAndReleaseWithSubsegment() { var parent = new Segment("parent", TraceId); var child = new Subsegment("child"); parent.AddSubsegment(child); Assert.AreEqual(parent.Reference, 2); Assert.AreEqual(child.Reference, 1); child.Release(); Assert.AreEqual(parent.Reference, 1); Assert.AreEqual(child.Reference, 0); Assert.IsFalse(parent.IsEmittable()); Assert.IsFalse(child.IsEmittable()); parent.Release(); Assert.AreEqual(parent.Reference, 0); Assert.IsTrue(parent.IsEmittable()); Assert.IsTrue(child.IsEmittable()); } [TestMethod] public void TestAddRefAndReleaseWithSubsegmentInReverseOrder() { var parent = new Segment("parent", TraceId); var child = new Subsegment("child"); parent.AddSubsegment(child); Assert.AreEqual(parent.Reference, 2); Assert.AreEqual(child.Reference, 1); parent.Release(); Assert.AreEqual(parent.Reference, 1); Assert.AreEqual(child.Reference, 1); Assert.IsFalse(parent.IsEmittable()); Assert.IsFalse(child.IsEmittable()); child.Release(); Assert.AreEqual(parent.Reference, 0); Assert.AreEqual(child.Reference, 0); Assert.IsTrue(parent.IsEmittable()); Assert.IsTrue(child.IsEmittable()); } [TestMethod] public void TestAddRefAndReleaseWithTwoSubsegment() { var s1 = new Segment("s1", TraceId); var s21 = new Subsegment("s21"); var s22 = new Subsegment("s22"); s1.AddSubsegment(s21); s1.AddSubsegment(s22); Assert.AreEqual(s1.Reference, 3); Assert.AreEqual(s21.Reference, 1); Assert.AreEqual(s22.Reference, 1); s21.Release(); Assert.AreEqual(s1.Reference, 2); Assert.AreEqual(s21.Reference, 0); Assert.AreEqual(s22.Reference, 1); Assert.IsFalse(s1.IsEmittable()); Assert.IsFalse(s21.IsEmittable()); Assert.IsFalse(s22.IsEmittable()); s22.Release(); Assert.AreEqual(s1.Reference, 1); Assert.AreEqual(s22.Reference, 0); Assert.IsFalse(s1.IsEmittable()); Assert.IsFalse(s22.IsEmittable()); s1.Release(); Assert.AreEqual(s1.Reference, 0); Assert.IsTrue(s1.IsEmittable()); Assert.IsTrue(s21.IsEmittable()); Assert.IsTrue(s22.IsEmittable()); } [TestMethod] public void TestAddRefAndReleaseWithThreeSegment() { var s1 = new Segment("s1", TraceId); var s2 = new Subsegment("s2"); var s3 = new Subsegment("s3"); s1.AddSubsegment(s2); s2.AddSubsegment(s3); Assert.AreEqual(s1.Reference, 2); Assert.AreEqual(s2.Reference, 2); Assert.AreEqual(s3.Reference, 1); s2.Release(); Assert.AreEqual(s1.Reference, 2); Assert.AreEqual(s2.Reference, 1); Assert.AreEqual(s3.Reference, 1); Assert.IsFalse(s1.IsEmittable()); Assert.IsFalse(s2.IsEmittable()); Assert.IsFalse(s3.IsEmittable()); s3.Release(); Assert.AreEqual(s1.Reference, 1); Assert.AreEqual(s2.Reference, 0); Assert.AreEqual(s3.Reference, 0); Assert.IsFalse(s1.IsEmittable()); Assert.IsFalse(s2.IsEmittable()); Assert.IsFalse(s3.IsEmittable()); s1.Release(); Assert.AreEqual(s1.Reference, 0); Assert.IsTrue(s1.IsEmittable()); Assert.IsTrue(s2.IsEmittable()); Assert.IsTrue(s3.IsEmittable()); } [TestMethod] public void TestAddException() { var segment = new Segment("test", TraceId); var e = new EntityNotAvailableException("Test someting wrong happens"); segment.AddException(e); Assert.IsTrue(segment.HasFault); Assert.IsFalse(segment.HasError); Assert.IsNotNull(segment.Cause); var descriptor = segment.Cause.ExceptionDescriptors[0]; Assert.AreEqual("Test someting wrong happens", descriptor.Message); Assert.AreEqual("EntityNotAvailableException", descriptor.Type); Assert.ReferenceEquals(e, descriptor.Exception); } [TestMethod] public void TestHttpOverwriteValue() { var segment = new Segment("test", TraceId); segment.Http["key"] = "value1"; segment.Http["key"] = "value2"; Assert.AreEqual("value2", segment.Http["key"]); } #if NETFRAMEWORK [TestMethod] public void TestSegmentIsSerializable() { string segmentName = "test"; string parentId = Entity.GenerateId(); Segment segment = new Segment(segmentName, TraceId, parentId); Exception ex = new ArgumentException("test can't be null"); segment.AddException(ex); segment.SetStartTimeToNow(); segment.SetEndTimeToNow(); string serviceKey = "key1"; string serviceValue = "value1"; segment.Service[serviceKey] = serviceValue; Segment segmentAfterSerialize = (Segment)SerializeAndDeserialize(segment); Assert.AreEqual(segmentName, segmentAfterSerialize.Name); Assert.AreEqual(TraceId, segmentAfterSerialize.TraceId); Assert.AreEqual(parentId, segmentAfterSerialize.ParentId); Assert.AreEqual(ex.Message, segmentAfterSerialize.Cause.ExceptionDescriptors[0].Message); Assert.AreEqual(segmentAfterSerialize.StartTime, segment.StartTime); Assert.AreEqual(segmentAfterSerialize.EndTime, segment.EndTime); Assert.AreEqual(segmentAfterSerialize.Service[serviceKey], segment.Service[serviceKey]); } [TestMethod] public void TestSubsegmentIsSerializable() { Subsegment subsegment = new Subsegment("test"); string testNamespace = "namespace"; subsegment.Namespace = testNamespace; Entity parent = new Segment("parent", TraceId); subsegment.Parent = parent; subsegment.HasStreamed = true; string type = "type1"; subsegment.Type = type; string precursorId = Entity.GenerateId(); subsegment.AddPrecursorId(precursorId); Subsegment subsegmentAfterSerialize = (Subsegment)SerializeAndDeserialize(subsegment); Assert.AreEqual(testNamespace, subsegmentAfterSerialize.Namespace); Assert.AreEqual(parent.TraceId, subsegmentAfterSerialize.Parent.TraceId); Assert.IsTrue(subsegmentAfterSerialize.HasStreamed); Assert.AreEqual(type, subsegmentAfterSerialize.Type); Assert.AreEqual(precursorId, subsegmentAfterSerialize.PrecursorIds.First()); } #endif private static object SerializeAndDeserialize(Object source) { IFormatter formatter = new BinaryFormatter(); Stream stream = new MemoryStream(); formatter.Serialize(stream, source); stream.Position = 0; object obj = formatter.Deserialize(stream); stream.Close(); return obj; } [TestMethod] public void TestSetUser() { var segment = new Segment("SegmentA"); segment.SetUser("UserA"); Assert.AreEqual("UserA", segment.GetUser()); } [TestMethod] public void TestSetUserWithNullValue() { var segment = new Segment("SegmentA"); Assert.ThrowsException(() => segment.SetUser(null)); } [TestMethod] public void TestSetUserWhenSegmentAlreadyStreamed() { var segment = new Segment("SegmentA"); segment.HasStreamed = true; Assert.ThrowsException(() => segment.SetUser("UserA"), "Segment SegmentA has already been emitted."); } } }