Skip to content

Commit

Permalink
feat: add Bugsnag.clearMetadata
Browse files Browse the repository at this point in the history
  • Loading branch information
robinmacharg committed Feb 12, 2020
1 parent f3c4f08 commit a4df655
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 25 deletions.
10 changes: 7 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ Bugsnag Notifiers on other platforms.
* Add a breadcrumb when Bugsnag first starts with the message "Bugsnag loaded"
[#445](https://github.com/bugsnag/bugsnag-cocoa/pull/445)

* `Bugsnag.addAttribute:value:tab:` is now `Bugsnag.addMetadataToSection::key:value:`
* `Bugsnag.addAttribute:value:tab:` is now `Bugsnag.addMetadataToSection:key:value:`
[#454](https://github.com/bugsnag/bugsnag-cocoa/pull/454)

* `[Bugsnag clearTab:]` is now `[Bugsnag clearMetadataInSection:]`
(Swift: `Bugsnag.clearMetadata(_ section)`)
* `[Bugsnag clearTab:]` is now `[Bugsnag clearMetadataInSection:]`
(Swift: `Bugsnag.clearMetadata(section:)`)
[#457](https://github.com/bugsnag/bugsnag-cocoa/pull/457)

* Added `[Bugsnag clearMetadataInSection:withKey:]`
(Swift: `Bugsnag.clearMetadata(section:key:)`)
[#462](https://github.com/bugsnag/bugsnag-cocoa/pull/462)

* Added `Bugsnag.getMetadata(_ section)`. The behaviour is: calling with a valid section
name will return the metadata for that section if it exists, or `nil` if it does not exist. Other,
Expand Down
25 changes: 18 additions & 7 deletions Source/Bugsnag.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,6 @@ static NSString *_Nonnull const BugsnagSeverityInfo = @"info";
value:(id _Nullable)value
NS_SWIFT_NAME(addMetadata(_:key:value:));

/** Remove custom data from Bugsnag reports.
*
* @param tabName The tab to clear.
*/
+ (void)clearMetadataInSection:(NSString *_Nonnull)tabName
NS_SWIFT_NAME(clearMetadata(_:));

/**
* Leave a "breadcrumb" log message, representing an action that occurred
* in your app, to aid with debugging.
Expand Down Expand Up @@ -286,4 +279,22 @@ static NSString *_Nonnull const BugsnagSeverityInfo = @"info";
+ (void)setBreadcrumbCapacity:(NSUInteger)capacity
__deprecated_msg("Use [BugsnagConfiguration setMaxBreadcrumbs:] instead");

/** Remove custom data from Bugsnag reports.
*
* @param sectionName The section to clear.
*/
+ (void)clearMetadataInSection:(NSString *_Nonnull)sectionName
NS_SWIFT_NAME(clearMetadata(section:));

/**
* Remove a key/value from a named matadata section. If either the section or the
* key do not exist no action will occur.
*
* @param sectionName The name of the section containing the value
* @param key The key to remove
*/
+ (void)clearMetadataInSection:(NSString *_Nonnull)sectionName
withKey:(NSString *_Nonnull)key
NS_SWIFT_NAME(clearMetadata(section:key:));

@end
21 changes: 15 additions & 6 deletions Source/Bugsnag.m
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,6 @@ + (void)addMetadataToSection:(NSString *_Nonnull)section
}
}

+ (void)clearMetadataInSection:(NSString *)section {
if ([self bugsnagStarted]) {
[self.notifier.configuration.metadata clearMetadataInSection:section];
}
}

+ (BOOL)bugsnagStarted {
if (!self.notifier.started) {
bsg_log_err(@"Ensure you have started Bugsnag with startWithApiKey: "
Expand Down Expand Up @@ -304,6 +298,21 @@ + (void)setWriteBinaryImagesForUserReported:
}
}

+ (void)clearMetadataInSection:(NSString *)sectionName {
if ([self bugsnagStarted]) {
[self.notifier.configuration.metadata clearMetadataInSection:sectionName];
}
}

+ (void)clearMetadataInSection:(NSString *_Nonnull)sectionName
withKey:(NSString *_Nonnull)key
{
if ([self bugsnagStarted]) {
[self.notifier.configuration.metadata clearMetadataInSection:sectionName
withKey:key];
}
}

+ (NSMutableDictionary *)getMetadata:(NSString *)section {
return [[[self configuration] metadata] getMetadata:section];
}
Expand Down
12 changes: 11 additions & 1 deletion Source/BugsnagMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,17 @@
NS_SWIFT_NAME(getMetadata(_:));

- (void)clearMetadataInSection:(NSString *_Nonnull)section
NS_SWIFT_NAME(clearMetadata(_:));
NS_SWIFT_NAME(clearMetadata(section:));
/**
* Remove a specific value for a specific key in a specific metadata section.
* If either section or key do not exist no action is taken.
*
* @param section The section name
* @param key the metadata key
*/
- (void)clearMetadataInSection:(NSString *_Nonnull)section
withKey:(NSString *_Nonnull)key
NS_SWIFT_NAME(clearMetadata(section:key:));

- (NSDictionary *_Nonnull)toDictionary;

Expand Down
13 changes: 13 additions & 0 deletions Source/BugsnagMetadata.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ - (id)initWithDictionary:(NSMutableDictionary *)dict {
return self;
}

// MARK: - <NSMutableCopying>

- (id)mutableCopyWithZone:(NSZone *)zone {
@synchronized(self) {
NSMutableDictionary *dict = [self.dictionary mutableCopy];
Expand All @@ -68,6 +70,17 @@ - (void)clearMetadataInSection:(NSString *)section {
[self.delegate metadataChanged:self];
}

- (void)clearMetadataInSection:(NSString *)section
withKey:(NSString *)key
{
@synchronized(self) {
if ([[[self dictionary] objectForKey:section] objectForKey:key]) {
[[[self dictionary] objectForKey:section] removeObjectForKey:key];
}
}
[self.delegate metadataChanged:self];
}

- (NSDictionary *)toDictionary {
@synchronized(self) {
return [NSDictionary dictionaryWithDictionary:self.dictionary];
Expand Down
58 changes: 58 additions & 0 deletions Tests/BugsnagMetadataTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// BugsnagMetadataTests.m
// Tests
//
// Created by Robin Macharg on 12/02/2020.
// Copyright © 2020 Bugsnag. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "BugsnagMetadata.h"

@interface BugsnagMetadataTests : XCTestCase

@end

@implementation BugsnagMetadataTests

- (void)testMutableCopyWithZone {

BugsnagMetadata *metadata = [BugsnagMetadata new];
[metadata addAttribute:@"myKey" withValue:@"myValue" toTabWithName:@"section1"];

BugsnagMetadata *copy = [metadata mutableCopyWithZone:nil];
XCTAssertNotEqual(metadata, copy);

// Until/unless it's decided otherwise the copy is a shallow one.
XCTAssertEqual([metadata getMetadata:@"section1"], [copy getMetadata:@"section1"]);
}

-(void)testClearMetadataInSectionWithKey {
BugsnagMetadata *metadata = [BugsnagMetadata new];
[metadata addAttribute:@"myKey1" withValue:@"myValue1" toTabWithName:@"section1"];
[metadata addAttribute:@"myKey2" withValue:@"myValue2" toTabWithName:@"section1"];
[metadata addAttribute:@"myKey3" withValue:@"myValue3" toTabWithName:@"section2"];

XCTAssertEqual([[metadata getMetadata:@"section1"] count], 2);
XCTAssertEqual([[metadata getMetadata:@"section2"] count], 1);

[metadata clearMetadataInSection:@"section1" withKey:@"myKey1"];
XCTAssertEqual([[metadata getMetadata:@"section1"] count], 1);
XCTAssertNil([[metadata getMetadata:@"section1"] valueForKey:@"myKey1"]);
XCTAssertEqual([[metadata getMetadata:@"section1"] valueForKey:@"myKey2"], @"myValue2");

// The short whole-section version
// Existing section
[metadata clearMetadataInSection:@"section2"];
XCTAssertNil([metadata getMetadata:@"section2"]);
XCTAssertEqual([[metadata getMetadata:@"section1"] valueForKey:@"myKey2"], @"myValue2");

// nonexistent sections
[metadata clearMetadataInSection:@"section3"];

// Add it back in, but different
[metadata addAttribute:@"myKey4" withValue:@"myValue4" toTabWithName:@"section2"];
XCTAssertEqual([[metadata getMetadata:@"section2"] valueForKey:@"myKey4"], @"myValue4");
}

@end
59 changes: 53 additions & 6 deletions Tests/BugsnagTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,28 @@ @interface BugsnagTests : XCTestCase

@implementation BugsnagTests

/**
* A boilerplate helper method to setup Bugsnag
*/
-(void)setUpBugsnagWillCallNotify:(bool)willNotify {
NSError *error;
BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1 error:&error];
if (willNotify) {
[configuration addBeforeSendBlock:^bool(NSDictionary * _Nonnull rawEventData, BugsnagEvent * _Nonnull reports) {
return false;
}];
}
[Bugsnag startBugsnagWithConfiguration:configuration];
}

/**
* Test that global metadata is added correctly, applied to each event, and
* deleted appropriately.
*/
- (void)testBugsnagMetadataAddition {

NSError *error;
BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1 error:&error];
[Bugsnag startBugsnagWithConfiguration:configuration];
[self setUpBugsnagWillCallNotify:true];

[Bugsnag addMetadataToSection:@"mySection1" key:@"aKey1" value:@"aValue1"];

// We should see our added metadata in every request. Let's try a couple:
Expand Down Expand Up @@ -66,9 +79,8 @@ - (void)testBugsnagMetadataAddition {
* return a section when there is one, or nil otherwise.
*/
- (void)testGetMetadata {
NSError *error;
BugsnagConfiguration *configuration = [[BugsnagConfiguration alloc] initWithApiKey:DUMMY_APIKEY_32CHAR_1 error:&error];
[Bugsnag startBugsnagWithConfiguration:configuration];
[self setUpBugsnagWillCallNotify:false];

XCTAssertNil([Bugsnag getMetadata:@"dummySection"]);
[Bugsnag addMetadataToSection:@"dummySection" key:@"aKey1" value:@"aValue1"];
NSMutableDictionary *section = [Bugsnag getMetadata:@"dummySection"];
Expand All @@ -77,4 +89,39 @@ - (void)testGetMetadata {
XCTAssertNil([Bugsnag getMetadata:@"anotherSection"]);
}

-(void)testClearMetadataInSectionWithKey {
[self setUpBugsnagWillCallNotify:false];

[Bugsnag addMetadataToSection:@"section1" key:@"myKey1" value:@"myValue1"];
[Bugsnag addMetadataToSection:@"section1" key:@"myKey2" value:@"myValue2"];
[Bugsnag addMetadataToSection:@"section2" key:@"myKey3" value:@"myValue3"];

XCTAssertEqual([[Bugsnag getMetadata:@"section1"] count], 2);
XCTAssertEqual([[Bugsnag getMetadata:@"section2"] count], 1);

[Bugsnag clearMetadataInSection:@"section1" withKey:@"myKey1"];
XCTAssertEqual([[Bugsnag getMetadata:@"section1"] count], 1);
XCTAssertNil([[Bugsnag getMetadata:@"section1"] valueForKey:@"myKey1"]);
XCTAssertEqual([[Bugsnag getMetadata:@"section1"] valueForKey:@"myKey2"], @"myValue2");
}

-(void)testClearMetadataInSection {
[self setUpBugsnagWillCallNotify:false];

[Bugsnag addMetadataToSection:@"section1" key:@"myKey1" value:@"myValue1"];
[Bugsnag addMetadataToSection:@"section1" key:@"myKey2" value:@"myValue2"];
[Bugsnag addMetadataToSection:@"section2" key:@"myKey3" value:@"myValue3"];

// Existing section
[Bugsnag clearMetadataInSection:@"section2"];
XCTAssertNil([Bugsnag getMetadata:@"section2"]);
XCTAssertEqual([[Bugsnag getMetadata:@"section1"] valueForKey:@"myKey1"], @"myValue1");

// nonexistent sections
[Bugsnag clearMetadataInSection:@"section3"];

// Add it back in, but different
[Bugsnag addMetadataToSection:@"section2" key:@"myKey4" value:@"myValue4"];
XCTAssertEqual([[Bugsnag getMetadata:@"section2"] valueForKey:@"myKey4"], @"myValue4");
}
@end
4 changes: 4 additions & 0 deletions iOS/Bugsnag.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
000E6EA523D8AC8C009D8194 /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 000E6EA123D8AC8C009D8194 /* VERSION */; };
000E6EA623D8AC8C009D8194 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 000E6EA223D8AC8C009D8194 /* CHANGELOG.md */; };
004753D423F1A4E2009884EB /* BugsnagMetadataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004753D323F1A4E2009884EB /* BugsnagMetadataTests.swift */; };
009131BA23F44619000810D9 /* BugsnagMetadataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 009131B923F44619000810D9 /* BugsnagMetadataTests.m */; };
00D7ACAD23E9C63000FBE4A7 /* BugsnagTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00D7ACAC23E9C63000FBE4A7 /* BugsnagTests.m */; };
00D7ACAF23EABBC800FBE4A7 /* BugsnagSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D7ACAE23EABBC800FBE4A7 /* BugsnagSwiftTests.swift */; };
4B47970A22A9AE1F00FF9C2E /* BugsnagEventFromKSCrashReportTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B47970922A9AE1F00FF9C2E /* BugsnagEventFromKSCrashReportTest.m */; };
Expand Down Expand Up @@ -416,6 +417,7 @@
000E6EA123D8AC8C009D8194 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = VERSION; path = ../VERSION; sourceTree = "<group>"; };
000E6EA223D8AC8C009D8194 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = "<group>"; };
004753D323F1A4E2009884EB /* BugsnagMetadataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugsnagMetadataTests.swift; sourceTree = "<group>"; };
009131B923F44619000810D9 /* BugsnagMetadataTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BugsnagMetadataTests.m; path = ../../Tests/BugsnagMetadataTests.m; sourceTree = "<group>"; };
00D7ACAC23E9C63000FBE4A7 /* BugsnagTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BugsnagTests.m; path = ../../Tests/BugsnagTests.m; sourceTree = "<group>"; };
00D7ACAE23EABBC800FBE4A7 /* BugsnagSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugsnagSwiftTests.swift; sourceTree = "<group>"; };
4B3B193422CA7B0900475354 /* BugsnagCollectionsBSGDictSetSafeObjectTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BugsnagCollectionsBSGDictSetSafeObjectTest.m; path = ../../Tests/BugsnagCollectionsBSGDictSetSafeObjectTest.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -764,6 +766,7 @@
000E6E9C23D8690E009D8194 /* Tests-Bridging-Header.h */,
000DF29323DB4B4900A883CE /* TestConstants.m */,
00D7ACAC23E9C63000FBE4A7 /* BugsnagTests.m */,
009131B923F44619000810D9 /* BugsnagMetadataTests.m */,
);
name = Tests;
path = BugsnagTests;
Expand Down Expand Up @@ -1255,6 +1258,7 @@
E784D2551FD70B3B004B01E1 /* KSCrashState_Tests.m in Sources */,
00D7ACAD23E9C63000FBE4A7 /* BugsnagTests.m in Sources */,
8A2C8F901C6BBFDD00846019 /* BugsnagEventTests.m in Sources */,
009131BA23F44619000810D9 /* BugsnagMetadataTests.m in Sources */,
E77316E31F73E89E00A14F06 /* BugsnagHandledStateTest.m in Sources */,
E70EE0961FD7071F00FA745C /* FileBasedTestCase.m in Sources */,
E7B3291A1FD707EC0098FC47 /* KSCrashReportConverter_Tests.m in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions iOS/BugsnagTests/Swift Tests/BugsnagSwiftTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ class BugsnagSwiftTests: XCTestCase {
func testClearMetadataInSectionIsExposedToSwiftCorrectly() {
try! Bugsnag.start(with: BugsnagConfiguration(DUMMY_APIKEY_32CHAR_1)!)
// We don't need to check method's functioning, only that we can call it this way
Bugsnag.clearMetadata("testSection")
Bugsnag.clearMetadata(section: "testSection")

let metadata = BugsnagMetadata()
metadata.clearMetadata("testSection2")
metadata.clearMetadata(section: "testSection2")
}
}

0 comments on commit a4df655

Please sign in to comment.