156 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			156 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								// Copyright (c) 2022 Sentry. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "SentryTests.h"
							 | 
						||
| 
								 | 
							
								#include "SentrySubsystem.h"
							 | 
						||
| 
								 | 
							
								#include "SentryEvent.h"
							 | 
						||
| 
								 | 
							
								#include "SentryTransaction.h"
							 | 
						||
| 
								 | 
							
								#include "SentryTransactionContext.h"
							 | 
						||
| 
								 | 
							
								#include "SentrySpan.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "UObject/UObjectGlobals.h"
							 | 
						||
| 
								 | 
							
								#include "Misc/AutomationTest.h"
							 | 
						||
| 
								 | 
							
								#include "Misc/DateTime.h"
							 | 
						||
| 
								 | 
							
								#include "Engine/Engine.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if WITH_AUTOMATION_TESTS
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BEGIN_DEFINE_SPEC(SentrySubsystemSpec, "Sentry.SentrySubsystem", EAutomationTestFlags::ProductFilter | SentryApplicationContextMask)
							 | 
						||
| 
								 | 
							
									USentrySubsystem* SentrySubsystem;
							 | 
						||
| 
								 | 
							
								END_DEFINE_SPEC(SentrySubsystemSpec)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void SentrySubsystemSpec::Define()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									BeforeEach([this]()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										SentrySubsystem = GEngine->GetEngineSubsystem<USentrySubsystem>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if(SentrySubsystem && !SentrySubsystem->IsEnabled())
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											SentrySubsystem->Initialize();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Describe("Capture Message", [this]()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										It("should return a non-null Event ID if message captured", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const USentryId* eventId = SentrySubsystem->CaptureMessage(FString(TEXT("Automation: Sentry test message")), ESentryLevel::Debug);
							 | 
						||
| 
								 | 
							
											TestNotNull("Event ID is non-null", eventId);
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										It("should always return non-null Event ID if scoped version used", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const FConfigureScopeNativeDelegate testDelegate;
							 | 
						||
| 
								 | 
							
											const USentryId* eventId = SentrySubsystem->CaptureMessageWithScope(FString(TEXT("Automation: Sentry test message with scope")), testDelegate, ESentryLevel::Debug);
							 | 
						||
| 
								 | 
							
											TestNotNull("Event ID is non-null", eventId);
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Describe("Capture Event", [this]()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										It("should return a non-null Event ID if event captured", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											USentryEvent* testEvent = NewObject<USentryEvent>();
							 | 
						||
| 
								 | 
							
											testEvent->SetMessage(TEXT("Automation: Sentry test event message"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const USentryId* eventId = SentrySubsystem->CaptureEvent(testEvent);
							 | 
						||
| 
								 | 
							
											TestNotNull("Event ID is non-null", eventId);
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										It("should always return non-null Event ID if scoped version used", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											USentryEvent* testEvent = NewObject<USentryEvent>();
							 | 
						||
| 
								 | 
							
											testEvent->SetMessage(TEXT("Automation: Sentry test event message"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const FConfigureScopeNativeDelegate testDelegate;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const USentryId* eventId = SentrySubsystem->CaptureEventWithScope(testEvent, testDelegate);
							 | 
						||
| 
								 | 
							
											TestNotNull("Event ID is non-null", eventId);
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Describe("Transaction", [this]()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										It("should be started and finished", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											USentryTransaction* transaction = SentrySubsystem->StartTransaction(TEXT("Automation transaction"), TEXT("Automation operation"));
							 | 
						||
| 
								 | 
							
											TestNotNull("Transaction is non-null", transaction);
							 | 
						||
| 
								 | 
							
											TestFalse("Transaction is not finished", transaction->IsFinished());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											USentrySpan* span = transaction->StartChild(TEXT("Automation span"), TEXT("Description text"));
							 | 
						||
| 
								 | 
							
											TestNotNull("Span is non-null", span);
							 | 
						||
| 
								 | 
							
											TestFalse("Span is not finished", span->IsFinished());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											USentrySpan* childSpan = span->StartChildWithTimestamp(TEXT("Automation child span"), TEXT("Description text"), FDateTime::UtcNow().ToUnixTimestamp());
							 | 
						||
| 
								 | 
							
											TestNotNull("Child span is non-null", childSpan);
							 | 
						||
| 
								 | 
							
											TestFalse("Child span is not finished", childSpan->IsFinished());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											childSpan->FinishWithTimestamp(FDateTime::UtcNow().ToUnixTimestamp());
							 | 
						||
| 
								 | 
							
											TestTrue("Child span is finished", childSpan->IsFinished());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											span->Finish();
							 | 
						||
| 
								 | 
							
											TestTrue("Span is finished", span->IsFinished());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											transaction->Finish();
							 | 
						||
| 
								 | 
							
											TestTrue("Transaction is finished", transaction->IsFinished());
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										It("should be started and finished with specific context", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											USentryTransactionContext* transactionContext = NewObject<USentryTransactionContext>();
							 | 
						||
| 
								 | 
							
											transactionContext->Initialize(TEXT("Automation transaction"), TEXT("Automation operation"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											USentryTransaction* transaction = SentrySubsystem->StartTransactionWithContext(transactionContext);
							 | 
						||
| 
								 | 
							
											TestNotNull("Transaction is non-null", transaction);
							 | 
						||
| 
								 | 
							
											TestFalse("Transaction is not finished", transaction->IsFinished());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											transaction->Finish();
							 | 
						||
| 
								 | 
							
											TestTrue("Transaction is finished", transaction->IsFinished());
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										It("should be started and finished with specific context and timings", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											USentryTransactionContext* transactionContext = NewObject<USentryTransactionContext>();
							 | 
						||
| 
								 | 
							
											transactionContext->Initialize(TEXT("Automation transaction"), TEXT("Automation operation"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											USentryTransaction* transaction = SentrySubsystem->StartTransactionWithContextAndTimestamp(transactionContext, FDateTime::UtcNow().ToUnixTimestamp());
							 | 
						||
| 
								 | 
							
											TestNotNull("Transaction is non-null", transaction);
							 | 
						||
| 
								 | 
							
											TestFalse("Transaction is not finished", transaction->IsFinished());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											transaction->FinishWithTimestamp(FDateTime::UtcNow().ToUnixTimestamp());
							 | 
						||
| 
								 | 
							
											TestTrue("Transaction is finished", transaction->IsFinished());
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Describe("Transaction context", [this]()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										It("should be created from trace and used to start a transaction", [this]()
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const FString inTrace = FString(TEXT("2674eb52d5874b13b560236d6c79ce8a-a0f9fdf04f1a63df-1"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											USentryTransactionContext* transactionContext = SentrySubsystem->ContinueTrace(inTrace, TArray<FString>());
							 | 
						||
| 
								 | 
							
											TestNotNull("Transaction context non-null", transactionContext);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											USentryTransaction* transaction = SentrySubsystem->StartTransactionWithContext(transactionContext);
							 | 
						||
| 
								 | 
							
											TestNotNull("Transaction is non-null", transaction);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											FString outTraceKey;
							 | 
						||
| 
								 | 
							
											FString outTraceValue;
							 | 
						||
| 
								 | 
							
											transaction->GetTrace(outTraceKey, outTraceValue);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											TArray<FString> outTraceParts;
							 | 
						||
| 
								 | 
							
											outTraceValue.ParseIntoArray(outTraceParts, TEXT("-"));
							 | 
						||
| 
								 | 
							
											TestTrue("Trace has valid amount of parts", outTraceParts.Num() >= 2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											TestEqual("Trace header", outTraceKey, TEXT("sentry-trace"));
							 | 
						||
| 
								 | 
							
											TestEqual("Trace ID", outTraceParts[0], TEXT("2674eb52d5874b13b560236d6c79ce8a"));
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									AfterEach([this]
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										SentrySubsystem->Close();
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |