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

test: split crash reporter tests into separate target #2899

Closed
wants to merge 9 commits into from

Conversation

armcknight
Copy link
Member

@armcknight armcknight commented Apr 13, 2023

  • reimplement some ojbc classes needed to move into the shared SentryTestUtils lib in swift since you cant mix them in a static library
  • reimplement some swift classes into objc since they were used from other objc files and i couldn't get the "-Swift.h" importation working
  • fixed some test assertions that started failing after making changes, not sure how they ever worked in the first place
  • fixed a bug with async frames in stack trace builder, also not sure how the associated test was passing

TODO:

  • figure out why SentryCrashInstallationTests.testUninstall` is failing, need some logging because it passes locally
  • give the tests a little more time to run, the Xcode 13 variants are timing out

#skip-changelog

…essary ojbc classes into swift since you cant mix them in a static library

fails to build because it looks like a c++ source is being included into the bridging header; or, the bridging header is being used incorrectly by the new target
…bridging header to tests bridging header and reimplement url delegate spy in objc because couldnt import the swift implementation into one of the objc test classes
@@ -1,17 +0,0 @@
import Foundation

class UrlSessionDelegateSpy: NSObject, URLSessionDelegate {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rewrote this in objc because it needed to be used in an objc test class and i couldn't get the "-Swift.h" import to work

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's such a small class so it should be fine.

@@ -1,26 +0,0 @@
import Sentry

class TestSentryUIDeviceWrapper: SentryUIDeviceWrapper {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one was simply moved/renamed like so many others into SentryTestUtils, but didn't diff that way

#import "SentryCrashMonitor_MachException.h"
#import "SentryCrashSystemCapabilities.h"
#import "SentryNSNotificationCenterWrapper.h"
#import "SentryTests-Swift.h"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason this generated swift header import stopped working, and i would've also needed one for the SentryTestUtils lib which also couldn't get working, so i just reimplemented this test class in Swift instead.

Comment on lines -2 to -12
#import "SentryDefines.h"
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/**
* Written in Objective-C because Swift doesn't allow you to call the constructor of
* TestSentryCrashAdapter. We override sharedInstance in the implementation file to make it work.
*/
@interface TestSentryCrashWrapper : SentryCrashWrapper
SENTRY_NO_INIT
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you cant mix objc and swift in a static lib, and i wanted to move this class into sentrytestutils because now it's used in both the main sdk test target and the new crash test target, i rewrote it in swift.

I also just removed the SENTRY_NO_INIT declaration from SentryCrashWrapper. Since it is passed around in the singleton dependency container, there's no reason to also have it be a singleton, so I figured it'll be fine to allow it to be alloc init'd. We shouldn't have much opportunity to need to accidentally do that in new places vs using the one vended by the dependency container. I converted all the calls to this singleton to use the one vended by the dependency container singleton.

#import "SentrySDK.h"
#import "SentryTests-Swift.h"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stopped working for some reason, which is why i had to rewrite UrlSessionDelegateSpy in objc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the info. We can fix it in another PR.

}
}

final class SentryCrashInstallationTests: XCTestCase {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewritten in swift, see my other comment on the old objc implementation that was removed.

@@ -92,8 +94,6 @@ typedef enum {
#define SentryCrashMonitorTypeRequired \
(SentryCrashMonitorTypeSystem | SentryCrashMonitorTypeApplicationState)

#define SentryCrashMonitorTypeNone 0
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wouldn't work in the new swift implementation of an objc impl that was using this, so i changed it to be a member of the enum instead.

@@ -0,0 +1,26 @@
import Sentry

public class TestSentryUIDeviceWrapper: SentryUIDeviceWrapper {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't rewritten, it was only renamed/moved, but didn't diff correctly. No changes in this file.

import Foundation
import Sentry

public class TestSentryCrashWrapper: SentryCrashWrapper {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewritten in swift, see later comment on the old objc implementation.

@brustolin
Copy link
Contributor

fixed a bug with async frames in stack trace builder, also not sure how the associated test was passing

This was fixed at #2898

@philipphofmann
Copy link
Member

I'm sorry I didn't get to that PR yet. I will give you a review on Monday.

Copy link
Member

@philipphofmann philipphofmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @armcknight for this great refactoring. We need to call all test targets in CI. It think it makes sense to run the test targets subsequentially for each matrix config for the unit tests

- runs-on: macos-11
platform: 'iOS'
xcode: '13.2.1'
test-destination-os: '13.7'
timeout-minutes: 15

otherwise, we end up with many more GH jobs. Maybe it makes sense to create multiple raw log artifacts per test target. We also need to ensure that the DerivedData Logs still work properly, and that the code coverage is not messed up.

FYI, I'm going to remove this piece of bash script as it's not required anymore this PR #2918

if [ $PLATFORM == "iOS" -a $OS == "12.4" ]; then
# Skip some tests that fail on iOS 12.4.
env NSUnbufferedIO=YES xcodebuild -workspace Sentry.xcworkspace \
-scheme Sentry -configuration $CONFIGURATION \
-destination "$DESTINATION" \
-skip-testing:"SentryTests/SentrySDKTests/testMemoryFootprintOfAddingBreadcrumbs" \
-skip-testing:"SentryTests/SentrySDKTests/testMemoryFootprintOfTransactions" \
test | tee raw-test-output.log | $RUBY_ENV_ARGS xcpretty -t && slather coverage --configuration $CONFIGURATION && exit ${PIPESTATUS[0]}
else

@@ -13,14 +13,6 @@

@implementation SentryCrashWrapper

+ (instancetype)sharedInstance
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: I think this change could be in an extra PR as it makes sense without all the other changes. Even if we agree not to proceed with this PR, this change would make it to the main branch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see #2941

@@ -155,7 +155,6 @@ - (void)testPipelineInit
id<SentryCrashReportFilter> filter = [[SentryCrashReportFilterPipeline alloc]
initWithFilters:[SentryCrashReportFilterPassthrough filter],
[SentryCrashReportFilterPassthrough filter], nil];
filter = filter;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment 😃

@@ -1,17 +0,0 @@
import Foundation

class UrlSessionDelegateSpy: NSObject, URLSessionDelegate {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's such a small class so it should be fine.

let sut = fixture.getSut(crashWrapper: SentryCrashWrapper.sharedInstance())
let sut = fixture.getSut(crashWrapper: SentryCrashWrapper()) // ???: should this be using TestSentryCrashWrapper?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that could make sense. If the test succeeds with TestSentryCrashWrapper, please use it.

#import "SentrySDK.h"
#import "SentryTests-Swift.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the info. We can fix it in another PR.


private extension SentryFrameRemoverTests {
/// Compare elements pairwise to see if the two input arrays are equivalent or not.
func equivalent(expected: [Frame], actual: [Frame]) -> Bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you did is okay. I also don't understand why the tests worked before.

for i in 0..<expected.count {
let nextExpected = expected[i]
let nextActual = actual[i]
if nextExpected.package != nextActual.package {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: I guess we shouldn't only just compare the package only. You could use:

extension Sentry.Frame {
open override func isEqual(_ object: Any?) -> Bool {

@brustolin
Copy link
Contributor

@armcknight As discussed during a meeting. Can we close this PR?

@armcknight armcknight closed this May 11, 2023
@armcknight armcknight deleted the armcknight/test/separate-crash-test-target branch May 11, 2023 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants