Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FetchBreadcrumbTrialLeaver and FetchBreadcrumbTrialManager #2410

Closed
wants to merge 1 commit into from
Closed
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
28 changes: 28 additions & 0 deletions Lottie.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,9 @@
82A552752A2FD44B00E47AC8 /* LottieAnimationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82A552742A2FD44B00E47AC8 /* LottieAnimationLayer.swift */; };
82A552762A2FD44B00E47AC8 /* LottieAnimationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82A552742A2FD44B00E47AC8 /* LottieAnimationLayer.swift */; };
82A552772A2FD44B00E47AC8 /* LottieAnimationLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82A552742A2FD44B00E47AC8 /* LottieAnimationLayer.swift */; };
877718D32BF7AFE100A106B6 /* FetchBreadcrumbTrialLeaver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 877718D22BF7AFE100A106B6 /* FetchBreadcrumbTrialLeaver.swift */; };
877718D52BF7B00800A106B6 /* FetchBreadcrumbTrialManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 877718D42BF7B00800A106B6 /* FetchBreadcrumbTrialManager.swift */; };
877718D82BF7B37900A106B6 /* FetchBreadcrumbTrialManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 877718D72BF7B37900A106B6 /* FetchBreadcrumbTrialManagerTests.swift */; };
A1D5BAAC27C731A500777D06 /* DataURLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1D5BAAB27C731A500777D06 /* DataURLTests.swift */; };
A40460592832C52B00ACFEDC /* BlendMode+Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40460582832C52B00ACFEDC /* BlendMode+Filter.swift */; };
A404605A2832C52B00ACFEDC /* BlendMode+Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40460582832C52B00ACFEDC /* BlendMode+Filter.swift */; };
Expand Down Expand Up @@ -1468,6 +1471,9 @@
6DEF696D2824A76C007D640F /* BundleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleTests.swift; sourceTree = "<group>"; };
7E48BF572860CECF00A39198 /* UnitBezier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitBezier.swift; sourceTree = "<group>"; };
82A552742A2FD44B00E47AC8 /* LottieAnimationLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieAnimationLayer.swift; sourceTree = "<group>"; };
877718D22BF7AFE100A106B6 /* FetchBreadcrumbTrialLeaver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchBreadcrumbTrialLeaver.swift; sourceTree = "<group>"; };
877718D42BF7B00800A106B6 /* FetchBreadcrumbTrialManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchBreadcrumbTrialManager.swift; sourceTree = "<group>"; };
877718D72BF7B37900A106B6 /* FetchBreadcrumbTrialManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchBreadcrumbTrialManagerTests.swift; sourceTree = "<group>"; };
A1D5BAAB27C731A500777D06 /* DataURLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataURLTests.swift; sourceTree = "<group>"; };
A40460582832C52B00ACFEDC /* BlendMode+Filter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BlendMode+Filter.swift"; sourceTree = "<group>"; };
AB3278122A71BA0400A9C9F1 /* View+ValueChanged.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ValueChanged.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1758,6 +1764,7 @@
2E8040BA27A07343006E74CB /* Tests */ = {
isa = PBXGroup;
children = (
877718D62BF7B36400A106B6 /* FetchBreadcrumbsTests */,
08F8B210289990B700CB5323 /* Samples */,
2E80489227A07377006E74CB /* __Snapshots__ */,
08F8B212289990CB00CB5323 /* SnapshotTests.swift */,
Expand Down Expand Up @@ -2244,6 +2251,7 @@
2EAF59C027A0798600E00531 /* Sources */ = {
isa = PBXGroup;
children = (
877718D12BF7AFCB00A106B6 /* FetchBreadcrumbs */,
2EAF59C127A0798700E00531 /* Public */,
2EAF59F327A0798700E00531 /* Private */,
);
Expand Down Expand Up @@ -2446,6 +2454,23 @@
path = DotLottie;
sourceTree = "<group>";
};
877718D12BF7AFCB00A106B6 /* FetchBreadcrumbs */ = {
isa = PBXGroup;
children = (
877718D22BF7AFE100A106B6 /* FetchBreadcrumbTrialLeaver.swift */,
877718D42BF7B00800A106B6 /* FetchBreadcrumbTrialManager.swift */,
);
path = FetchBreadcrumbs;
sourceTree = "<group>";
};
877718D62BF7B36400A106B6 /* FetchBreadcrumbsTests */ = {
isa = PBXGroup;
children = (
877718D72BF7B37900A106B6 /* FetchBreadcrumbTrialManagerTests.swift */,
);
path = FetchBreadcrumbsTests;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -3133,11 +3158,13 @@
6C4877FF28FF20140005AF07 /* DotLottieAnimation.swift in Sources */,
2E9C97262822F43100677516 /* StrokeAnimation.swift in Sources */,
2E9C97382822F43100677516 /* VisibilityAnimation.swift in Sources */,
877718D52BF7B00800A106B6 /* FetchBreadcrumbTrialManager.swift in Sources */,
2EAF5AD727A0798700E00531 /* Vectors.swift in Sources */,
2E9C95E22822F43100677516 /* Group.swift in Sources */,
2E9C97112822F43100677516 /* Keyframes+combined.swift in Sources */,
0887347B28F0CCDD00458627 /* LottieAnimationView.swift in Sources */,
2E9C966F2822F43100677516 /* LayerTextProvider.swift in Sources */,
877718D32BF7AFE100A106B6 /* FetchBreadcrumbTrialLeaver.swift in Sources */,
2E9C97172822F43100677516 /* CAAnimation+TimingConfiguration.swift in Sources */,
08E2075D2A56014E002DCE17 /* EpoxyModeled.swift in Sources */,
6C4878602901D8C70005AF07 /* DotLottieImageProvider.swift in Sources */,
Expand Down Expand Up @@ -3260,6 +3287,7 @@
2E8044AE27A07347006E74CB /* Snapshotting+presentationLayer.swift in Sources */,
089C50C22ABA0C6D007903D3 /* LoggingTests.swift in Sources */,
36E57EAC28AF7ADF00B7EFDA /* HardcodedTextProvider.swift in Sources */,
877718D82BF7B37900A106B6 /* FetchBreadcrumbTrialManagerTests.swift in Sources */,
2E72128527BB32DB0027BC56 /* PerformanceTests.swift in Sources */,
6DB3BDC328245AA2002A276D /* ParsingTests.swift in Sources */,
080F5FDC2AB1075000ADC32C /* TextProviderTests.swift in Sources */,
Expand Down
24 changes: 24 additions & 0 deletions Sources/FetchBreadcrumbs/FetchBreadcrumbTrialLeaver.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// FetchBreadcrumbTrialManager.swift
// Lottie-iOS
//
// Created by Omar Masri on 5/17/24.
//

import Foundation

/// A protocol that needs to be implemented by the main app and it's value must be passed to `FetchBreadcrumbTrialManager.shared` thorough the `configure(:any FetchBreadcrumbTrialLeaver)` method
/// no providing this value will make the`FetchBreadcrumbTrialManager` useless.
public protocol FetchBreadcrumbTrialLeaver {

/// Called to leave a breadcrumb in the execution path of the Lottie sdk
/// - Parameters:
/// - entity: The name of the entity (class, struct, enum, actor) this method id triggered at
/// - point: Any string that can indicate the exact line/process being executed.
/// - value: an optional `Any` that represent a specific value that we were trying to process.
func leaveTrace(
in entity: String,
at point: String,
with value: Any?
)
}
29 changes: 29 additions & 0 deletions Sources/FetchBreadcrumbs/FetchBreadcrumbTrialManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// FetchBreadcrumbTrialManager.swift
// Lottie-iOS
//
// Created by Omar Masri on 5/17/24.
//

import Foundation

/// Used to leave BreadcrumbTrial in some of Lottie operation we do
public final class FetchBreadcrumbTrialManager {
public static let shared: FetchBreadcrumbTrialManager = .init()

private var traceLeaver: (any FetchBreadcrumbTrialLeaver)?

init(traceLeaver: (any FetchBreadcrumbTrialLeaver)? = nil) {
self.traceLeaver = traceLeaver
}

/// Configure the traceLeaver value that will be used to leave breadcrumbs
/// - Parameter traceLeaver: any FetchBreadcrumbTrialLeaver
public func configure(with traceLeaver: any FetchBreadcrumbTrialLeaver) {
self.traceLeaver = traceLeaver
}

func dropBreadcrumb(in entity: String, at point: String, with value: Any? = nil) {
traceLeaver?.leaveTrace(in: entity, at: point, with: value)
}
}
70 changes: 51 additions & 19 deletions Sources/Private/Utility/Primitives/CGPointExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,60 @@
import CoreGraphics

extension CGPoint: AnyInitializable {
// MARK: Breadcrumb

// MARK: Lifecycle
private static var BreadcrumbEntityName: String {
"CGPointExtension.swift, CGPoint(value: Any) custom initializer"
}

// MARK: Lifecycle

init(value: Any) throws {
if let dictionary = value as? [String: CGFloat] {
let x: CGFloat = try dictionary.value(for: CodingKeys.x)
let y: CGFloat = try dictionary.value(for: CodingKeys.y)
self.init(x: x, y: y)
} else if
let array = value as? [CGFloat],
array.count > 1
{
self.init(x: array[0], y: array[1])
} else {
throw InitializableError.invalidInput()
init(value: Any) throws {
FetchBreadcrumbTrialManager.shared.dropBreadcrumb(
in: Self.BreadcrumbEntityName,
at: "Start point",
with: value
)
if let dictionary = value as? [String: CGFloat] {
FetchBreadcrumbTrialManager.shared.dropBreadcrumb(
in: Self.BreadcrumbEntityName,
at: "value is [String: CGFloat] type, will start initializing CGFloat struct now",
with: value
)
let x: CGFloat = try dictionary.value(for: CodingKeys.x)
let y: CGFloat = try dictionary.value(for: CodingKeys.y)
self.init(x: x, y: y)
FetchBreadcrumbTrialManager.shared.dropBreadcrumb(
in: Self.BreadcrumbEntityName,
at: "CGFloat is successfully initialized"
)
} else if
let array = value as? [CGFloat],
array.count > 1
{
FetchBreadcrumbTrialManager.shared.dropBreadcrumb(
in: Self.BreadcrumbEntityName,
at: "value is [CGFloat] type, will start initializing CGFloat struct now",
with: value
)
self.init(x: array[0], y: array[1])
FetchBreadcrumbTrialManager.shared.dropBreadcrumb(
in: Self.BreadcrumbEntityName,
at: "CGFloat is successfully initialized"
)
} else {
FetchBreadcrumbTrialManager.shared.dropBreadcrumb(
in: Self.BreadcrumbEntityName,
at: "CGFloat is throwing an invalidInput error"
)
throw InitializableError.invalidInput()
}
}
}

// MARK: Private
// MARK: Private

private enum CodingKeys: String {
case x
case y
}
private enum CodingKeys: String {
case x
case y
}
}
66 changes: 66 additions & 0 deletions Tests/FetchBreadcrumbsTests/FetchBreadcrumbTrialManagerTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// FetchBreadcrumbTrialManagerTests.swift
// LottieTests
//
// Created by Omar Masri on 5/17/24.
//

import XCTest
@testable import Lottie

final class FetchBreadcrumbTrialManagerTests: XCTestCase {

typealias SUT = FetchBreadcrumbTrialManager

private var sut: SUT!
private var trialLeaver: FetchBreadcrumbTrialLeaverMock!

override func setUp() {
super.setUp()

sut = .init()
trialLeaver = FetchBreadcrumbTrialLeaverMock()
}

override func tearDown() {
sut = nil
trialLeaver = nil
super.tearDown()
}

func test_dropBreadcrumb() {
sut.configure(with: trialLeaver)

sut.dropBreadcrumb(in: "some-entity", at: "some-point", with: ["value"])

XCTAssertEqual(trialLeaver._leaveTraceLastInvocation?.entity, "some-entity")
XCTAssertEqual(trialLeaver._leaveTraceLastInvocation?.point, "some-point")
XCTAssertEqual(trialLeaver._leaveTraceLastInvocation?.value as? [String], ["value"])
}

func test_updateManagerConfig() {
sut.configure(with: trialLeaver)
sut.dropBreadcrumb(in: "some-entity", at: "some-point", with: ["value"])

XCTAssertEqual(trialLeaver._leaveTraceInvocationCount, 1)

let updatedTrialLeaver = FetchBreadcrumbTrialLeaverMock()
sut.configure(with: updatedTrialLeaver)

XCTAssertEqual(updatedTrialLeaver._leaveTraceInvocationCount, 0)

sut.dropBreadcrumb(in: "some-entity", at: "some-point", with: ["value"])
XCTAssertEqual(updatedTrialLeaver._leaveTraceInvocationCount, 1)
}
}

fileprivate final class FetchBreadcrumbTrialLeaverMock: FetchBreadcrumbTrialLeaver {

var _leaveTraceLastInvocation: (entity: String, point: String, value: Any?)?
var _leaveTraceInvocationCount = 0

func leaveTrace(in entity: String, at point: String, with value: Any?) {
_leaveTraceInvocationCount += 1
_leaveTraceLastInvocation = (entity, point, value)
}
}
Loading