Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions src/Microsoft.CorrelationVector.UnitTests/CorrelationVectorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Expand Down Expand Up @@ -30,6 +31,18 @@ public void CreateV2CorrelationVectorTest()
Assert.AreEqual(2, splitVector.Length, "Correlation Vector should be created with two components separated by a '.'");
Assert.AreEqual(22, splitVector[0].Length, "Correlation Vector base should be 22 characters long");
Assert.AreEqual("0", splitVector[1], "Correlation Vector extension should start with zero");
}

[TestMethod]
public void CreateV3CorrelationVectorTest()
{
var correlationVector = new CorrelationVectorV3();
var splitVector = correlationVector.Value.Split('.');

Assert.AreEqual(3, splitVector.Length, "Correlation Vector should be created with three components separated by a '.'");
Assert.AreEqual("A", splitVector[0], "Correlation Vector v3 should start with \"A\".");
Assert.AreEqual(22, splitVector[1].Length, "Correlation Vector base should be 22 characters long");
Assert.AreEqual("0", splitVector[2], "Correlation Vector extension should start with zero");
}

[TestMethod]
Expand All @@ -54,6 +67,19 @@ public void CreateCorrelationVectorFromGuidTestV2()
Assert.AreEqual(2, splitVector.Length, "Correlation Vector should be created with two components separated by a '.'");
Assert.AreEqual(22, splitVector[0].Length, "Correlation Vector base should be 22 characters long");
Assert.AreEqual("0", splitVector[1], "Correlation Vector extension should start with zero");
}

[TestMethod]
public void CreateCorrelationVectorFromGuidTestV3()
{
var guid = System.Guid.NewGuid();
var correlationVector = new CorrelationVectorV3(guid);
var splitVector = correlationVector.Value.Split('.');

Assert.AreEqual(3, splitVector.Length, "Correlation Vector should be created with three components separated by a '.'");
Assert.AreEqual("A", splitVector[0], "Correlation Vector v3 should start with \"A\".");
Assert.AreEqual(22, splitVector[1].Length, "Correlation Vector base should be 22 characters long");
Assert.AreEqual("0", splitVector[2], "Correlation Vector extension should start with zero");
}

[TestMethod]
Expand All @@ -72,6 +98,16 @@ public void GetBaseAsGuidV2Test()
var correlationVector = new CorrelationVectorV2(guid);
Guid baseAsGuid = correlationVector.GetBaseAsGuid();

Assert.AreEqual(guid, baseAsGuid, "Correlation Vector base as a guid should be the same as the initial guid");
}

[TestMethod]
public void GetBaseAsGuidV3Test()
{
var guid = System.Guid.NewGuid();
var correlationVector = new CorrelationVectorV3(guid);
Guid baseAsGuid = correlationVector.GetBaseAsGuid();

Assert.AreEqual(guid, baseAsGuid, "Correlation Vector base as a guid should be the same as the initial guid");
}

Expand Down Expand Up @@ -153,6 +189,20 @@ public void ParseCorrelationVectorV2Test()
Assert.AreEqual("3", splitVector[1], "Correlation Vector extension was not parsed properly");
Assert.AreEqual("4", splitVector[2], "Correlation Vector extension was not parsed properly");
Assert.AreEqual("5", splitVector[3], "Correlation Vector extension was not parsed properly");
}

[TestMethod]
public void ParseCorrelationVectorV3Test()
{
var correlationVector = CorrelationVector.Parse("A.Y58xO9ov0kmpPvkiuzMUVA.3.4.A");
var splitVector = correlationVector.Value.Split('.');

Assert.AreEqual(CorrelationVectorVersion.V3, correlationVector.Version, "Correlation Vector version should be V3");
Assert.AreEqual(5, splitVector.Length, "Correlation Vector was not parsed properly");
Assert.AreEqual("Y58xO9ov0kmpPvkiuzMUVA", correlationVector.Base, "Correlation Vector base was not parsed properly");
Assert.AreEqual("3", splitVector[2], "Correlation Vector extension was not parsed properly");
Assert.AreEqual("4", splitVector[3], "Correlation Vector extension was not parsed properly");
Assert.AreEqual(0xA, correlationVector.Extension, "Correlation Vector extension was not parsed properly");
}

[TestMethod]
Expand Down Expand Up @@ -254,6 +304,15 @@ public void ThrowWithTooBigCorrelationVectorValueV2()
/* Bigger than 127 chars */
var vector = CorrelationVector.Extend("KZY+dsX2jEaZesgCPjJ2Ng.2147483647.2147483647.2147483647.2147483647.2147483647.2147483647.2147483647.2147483647.2147483647.2147483647");
});
}

[TestMethod]
public void ResetWithTooBigCorrelationVectorValueV3()
{
CorrelationVector.ValidateCorrelationVectorDuringCreation = true;
/* Bigger than 127 chars */
var vector = CorrelationVector.Extend("A.KZY+dsX2jEaZesgCPjJ2Ng.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF");
Assert.IsTrue(vector.Value.Contains("#"), "Reset vector must contain reset indicator");
}

[TestMethod]
Expand Down Expand Up @@ -317,6 +376,7 @@ public void SpinSortValidation()
for (int i = 0; i < 100; i++)
{
// The cV after a Spin will look like <cvBase>.0.<spinValue>.0, so the spinValue is at index = 2.
CorrelationVector newVector = CorrelationVector.Spin(vector.Value, spinParameters);
var spinValue = uint.Parse(CorrelationVector.Spin(vector.Value, spinParameters).Value.Split('.')[2]);

// Count the number of times the counter wraps.
Expand All @@ -335,6 +395,54 @@ public void SpinSortValidation()
Assert.IsTrue(wrappedCounter <= 1);
}

[TestMethod]
public void SpinSortValidationV3()
{
var vector = new CorrelationVectorV3();
var spinParameters = new SpinParameters
{
Entropy = SpinEntropy.Four,
Interval = SpinCounterInterval.Fine,
Periodicity = SpinCounterPeriodicity.Long
};

ulong lastSpinValue = 0;
var wrappedCounter = 0;
for (int i = 0; i < 100; i++)
{
// The cV after a Spin will look like <cvBase>.0_<spinValue>.0, so the spinValue is at index = 2.
CorrelationVector newVector = CorrelationVectorV3.Spin(vector.Value, spinParameters);
string hexValue = newVector.Value.Split('.', '_')[3];
var spinValue = ulong.Parse(hexValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);

// Count the number of times the counter wraps.
if (spinValue <= lastSpinValue)
{
wrappedCounter++;
}

lastSpinValue = spinValue;

// Wait for 10ms.
Task.Delay(10).Wait();
}

// The counter should wrap at most 1 time.
Assert.IsTrue(wrappedCounter <= 1);
}

[TestMethod]
public void TestResetV3()
{
CorrelationVector.ValidateCorrelationVectorDuringCreation = false;
const string baseVector = "A.KZY+dsX2jEaZesgCPjJ2Ng.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.FFF";

// we hit 127 chars limit, will reset vector
Tuple<string, string> resetValues = CorrelationVector.Parse(baseVector).Reset();
Assert.IsTrue(resetValues.Item1.Contains("#"), "Reset vector must contain reset indicator");
Assert.AreEqual(baseVector, resetValues.Item2, "The stored vector is different from the base vector.");
}

[TestMethod]
public void SpinPastMaxWithTerminationSignV2()
{
Expand All @@ -346,6 +454,31 @@ public void SpinPastMaxWithTerminationSignV2()
Assert.AreEqual(string.Concat(baseVector, CorrelationVectorV2.TerminationSign), vector.Value);
}

[TestMethod]
public void SpinPastMaxWithResetV3()
{
CorrelationVector.ValidateCorrelationVectorDuringCreation = false;
const string baseVector = "A.KZY+dsX2jEaZesgCPjJ2Ng.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF";

// we hit 127 chars limit, will reset vector and show value
var vector = CorrelationVector.Spin(baseVector);
Assert.IsTrue(vector.Value.Contains("#"), "Reset vector must contain reset indicator");
}

[TestMethod]
public void IncrementPastMaxWithResetV3()
{
CorrelationVector.ValidateCorrelationVectorDuringCreation = false;
const string baseVector = "A.PmvzQKgYek6Sdk/T5sWaqw.1.FA.A1.23_B6A5E62FC38E9974.1_B6A6A13E588CF82F.2A.AB.213_B6A92D24A00C0F9B.47.8B.12.34.A123.2B.23.41.FF";

var vectorToIncrement = CorrelationVector.Parse(baseVector);
// we hit 127 chars limit, will reset vector and show value
var incrementedString = vectorToIncrement.Increment();
var newVector = CorrelationVector.Parse(incrementedString);
Assert.IsTrue(incrementedString.Contains("#"), "Reset vector must contain reset indicator");
Assert.AreEqual(0x100, newVector.Extension, "Vector with extension FF should increment to 100");
}

[TestMethod]
public void ExtendPastMaxWithTerminationSign()
{
Expand All @@ -368,6 +501,39 @@ public void ExtendPastMaxWithTerminationSignV2()
Assert.AreEqual(string.Concat(baseVector, CorrelationVectorV2.TerminationSign), vector.Value);
}

[TestMethod]
public void ExtendPastMaxWithResetV3()
{
CorrelationVector.ValidateCorrelationVectorDuringCreation = false;
const string baseVector = "A.KZY+dsX2jEaZesgCPjJ2Ng.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.7FFFFFFF.FFF";

// we hit 127 chars limit, will append "!" to vector
var vector = CorrelationVector.Extend(baseVector);
Assert.IsTrue(vector.Value.Contains("#"), "Reset vector must contain reset indicator");
}

[TestMethod]
public void ConvertTraceparentV3()
{
const string traceparent = "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01";
string[] traceSections = traceparent.Split('-');
var vector = CorrelationVectorV3.Span(traceparent);

// Convert trace ID to bytes
var traceIDBytes = new byte[traceSections[1].Length / 2];
for (var i = 0; i < traceIDBytes.Length; i++)
{
traceIDBytes[i] = Convert.ToByte(traceSections[1].Substring(i * 2, 2), 16);
}

// Convert 64-bit representation of base to bytes
string paddedBase = vector.Base.PadRight(24, '=');
byte[] cvBaseBytes = Convert.FromBase64String(paddedBase);
Assert.IsTrue(vector.Value.Contains("-"), "Span vector must contain span indicator");
Assert.AreEqual(22, vector.Base.Length, "Correlation Vector base should be 22 characters long");
CollectionAssert.AreEqual(traceIDBytes, cvBaseBytes, "Trace ID bytes and cV base bytes must be equal");
}

[TestMethod]
public void ImmutableWithTerminationSign()
{
Expand Down
19 changes: 17 additions & 2 deletions src/Microsoft.CorrelationVector/CorrelationVector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ private static CorrelationVectorVersion InferVersion(string correlationVector)
{
return CorrelationVectorVersion.V2;
}
else if (index == 1)
{
// cV version indicated by starting single letter for V3 and after
if (correlationVector.Substring(0, index) == "A")
{
return CorrelationVectorVersion.V3;
}
else
{
//By default not reporting error, just return V1
return CorrelationVectorVersion.V1;
}
}
else
{
//By default not reporting error, just return V1
Expand All @@ -89,14 +102,14 @@ private static CorrelationVectorVersion InferVersion(string correlationVector)
public static CorrelationVector Parse(string correlationVector)
{
CorrelationVectorVersion version = InferVersion(correlationVector);
return RunStaticMethod(correlationVector, version, CorrelationVectorV1.Parse, CorrelationVectorV2.Parse);
return RunStaticMethod(correlationVector, version, CorrelationVectorV1.Parse, CorrelationVectorV2.Parse, CorrelationVectorV3.Parse);

}

public static CorrelationVector Extend(string correlationVector)
{
CorrelationVectorVersion version = InferVersion(correlationVector);
return RunStaticMethod(correlationVector, version, CorrelationVectorV1.Extend, CorrelationVectorV2.Extend);
return RunStaticMethod(correlationVector, version, CorrelationVectorV1.Extend, CorrelationVectorV2.Extend, CorrelationVectorV3.Extend);
}

public static CorrelationVector Spin(string correlationVector)
Expand All @@ -119,6 +132,8 @@ public static CorrelationVector Spin(string correlationVector, SpinParameters pa
return CorrelationVectorV1.Spin(correlationVector, parameters);
case CorrelationVectorVersion.V2:
return CorrelationVectorV2.Spin(correlationVector, parameters);
case CorrelationVectorVersion.V3:
return CorrelationVectorV3.Spin(correlationVector, parameters);
default:
return null;
}
Expand Down
Loading