//----------------------------------------------------------------------------- // // 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 Amazon.XRay.Recorder.UnitTests.Tools; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.EntityFrameworkCore; using Amazon.XRay.Recorder.Core; using System.Linq; using Microsoft.Data.Sqlite; using Amazon.XRay.Recorder.Core.Internal.Entities; namespace Amazon.XRay.Recorder.UnitTests { [TestClass] public class EfCoreTests : TestBase { private const String _connectionString = "datasource=:memory:"; private const String _queryString = "SELECT \"u\".\"UserId\"\r\nFROM \"Users\" AS \"u\"\r\nWHERE \"u\".\"UserId\" = 1"; private const String _dbVersion = "3.28.0"; private SqliteConnection connection = null; [TestInitialize] public void TestInitialize() { // In-memory database only exists while the connection is open connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); } [TestCleanup] public new void TestCleanup() { connection.Close(); base.TestCleanup(); } [TestMethod] public void Test_EFCore_successful_query() { // Arrange var recorder = new AWSXRayRecorder(); recorder.BeginSegment("TestSegment"); var context = GetTestEFContext(true); // Act var users = context.Users.Where(u => u.UserId == 1).ToList(); // Assert var segment = recorder.TraceContext.GetEntity(); Assert.AreEqual(3, segment.Subsegments.Count); //2 subsegments from validating the db and 1 from the actual query var query_subsegment = segment.Subsegments[2]; AssertQueryCollected(query_subsegment); recorder.EndSegment(); } [TestMethod] public void Test_EFCore_unsuccessful_query() { var recorder = new AWSXRayRecorder(); recorder.BeginSegment("TestSegment"); var context = GetTestEFContext(false); var users = context.Users.Where(u => u.UserId == 1).ToList(); var segment = recorder.TraceContext.GetEntity(); Assert.AreEqual(3, segment.Subsegments.Count); var query_subsegment = segment.Subsegments[2]; AssertQueryNotCollected(query_subsegment); recorder.EndSegment(); } [TestMethod] public void Test_EFCore_query_with_exception() { var recorder = new AWSXRayRecorder(); recorder.BeginSegment("TestSegment"); var context = GetTestEFContext(true); try { context.Database.ExecuteSqlInterpolated($"Select * From FakeTable"); // A false sql command which results in 'no such table: FakeTable' exception } catch { // ignore } var segment = recorder.TraceContext.GetEntity(); Assert.AreEqual(3, segment.Subsegments.Count); var subsegment = segment.Subsegments[2]; Assert.AreEqual(true, subsegment.HasFault); recorder.EndSegment(); } private void AssertQueryCollected(Subsegment subsegment) { AssertExpectedSqlInformation(subsegment); Assert.IsTrue(subsegment.Sql.ContainsKey("sanitized_query")); } private void AssertQueryNotCollected(Subsegment subsegment) { AssertExpectedSqlInformation(subsegment); Assert.IsFalse(subsegment.Sql.ContainsKey("sanitized_query")); } private void AssertExpectedSqlInformation(Subsegment subsegment) { Assert.IsNotNull(subsegment); Assert.IsNotNull(subsegment.Sql); Assert.AreEqual(_connectionString, subsegment.Sql["connection_string"]); Assert.AreEqual(connection.ServerVersion, subsegment.Sql["database_version"]); } private TestEFContext GetTestEFContext(bool collectSqlQueries) { var options = new DbContextOptionsBuilder() .UseSqlite(connection) .AddXRayInterceptor(collectSqlQueries) .Options; var context = new TestEFContext(options); context.Database.EnsureCreated(); return context; } } }