1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #import <Cocoa/Cocoa.h> 6 7 #import "base/mac/scoped_nsexception_enabler.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram_samples.h" 11 #include "base/metrics/statistics_recorder.h" 12 #import "chrome/browser/chrome_browser_application_mac.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 using base::HistogramBase; 16 using base::HistogramSamples; 17 using base::StatisticsRecorder; 18 19 namespace chrome_browser_application_mac { 20 21 // Generate an NSException with the given name. 22 NSException* ExceptionNamed(NSString* name) { 23 base::mac::ScopedNSExceptionEnabler enabler; 24 25 return [NSException exceptionWithName:name 26 reason:@"No reason given" 27 userInfo:nil]; 28 } 29 30 // Helper to keep binning expectations readible. 31 size_t BinForExceptionNamed(NSString* name) { 32 return BinForException(ExceptionNamed(name)); 33 } 34 35 TEST(ChromeApplicationMacTest, ExceptionBinning) { 36 // These exceptions must be in this order. 37 EXPECT_EQ(BinForExceptionNamed(NSGenericException), 0U); 38 EXPECT_EQ(BinForExceptionNamed(NSRangeException), 1U); 39 EXPECT_EQ(BinForExceptionNamed(NSInvalidArgumentException), 2U); 40 EXPECT_EQ(BinForExceptionNamed(NSMallocException), 3U); 41 42 // Random other exceptions map to |kUnknownNSException|. 43 EXPECT_EQ(BinForExceptionNamed(@"CustomName"), kUnknownNSException); 44 EXPECT_EQ(BinForExceptionNamed(@"Custom Name"), kUnknownNSException); 45 EXPECT_EQ(BinForExceptionNamed(@""), kUnknownNSException); 46 EXPECT_EQ(BinForException(nil), kUnknownNSException); 47 } 48 49 TEST(ChromeApplicationMacTest, RecordException) { 50 // Start up a histogram recorder. 51 // TODO(rtenneti): Leaks StatisticsRecorder and will update suppressions. 52 base::StatisticsRecorder::Initialize(); 53 54 StatisticsRecorder::Histograms histograms; 55 StatisticsRecorder::GetSnapshot("OSX.NSException", &histograms); 56 EXPECT_EQ(0U, histograms.size()); 57 58 // Record some known exceptions. 59 RecordExceptionWithUma(ExceptionNamed(NSGenericException)); 60 RecordExceptionWithUma(ExceptionNamed(NSGenericException)); 61 RecordExceptionWithUma(ExceptionNamed(NSGenericException)); 62 RecordExceptionWithUma(ExceptionNamed(NSGenericException)); 63 RecordExceptionWithUma(ExceptionNamed(NSRangeException)); 64 RecordExceptionWithUma(ExceptionNamed(NSInvalidArgumentException)); 65 RecordExceptionWithUma(ExceptionNamed(NSInvalidArgumentException)); 66 RecordExceptionWithUma(ExceptionNamed(NSInvalidArgumentException)); 67 RecordExceptionWithUma(ExceptionNamed(NSMallocException)); 68 RecordExceptionWithUma(ExceptionNamed(NSMallocException)); 69 70 // Record some unknown exceptions. 71 RecordExceptionWithUma(ExceptionNamed(@"CustomName")); 72 RecordExceptionWithUma(ExceptionNamed(@"Custom Name")); 73 RecordExceptionWithUma(ExceptionNamed(@"")); 74 RecordExceptionWithUma(nil); 75 76 // We should have exactly the right number of exceptions. 77 StatisticsRecorder::GetSnapshot("OSX.NSException", &histograms); 78 EXPECT_EQ(1U, histograms.size()); 79 EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, histograms[0]->flags()); 80 81 scoped_ptr<HistogramSamples> samples(histograms[0]->SnapshotSamples()); 82 EXPECT_EQ(4, samples->GetCount(0)); 83 EXPECT_EQ(1, samples->GetCount(1)); 84 EXPECT_EQ(3, samples->GetCount(2)); 85 EXPECT_EQ(2, samples->GetCount(3)); 86 87 // The unknown exceptions should end up in the overflow bucket. 88 EXPECT_TRUE(histograms[0]->HasConstructionArguments(1, 89 kUnknownNSException, 90 kUnknownNSException + 1)); 91 EXPECT_EQ(4, samples->GetCount(kUnknownNSException)); 92 } 93 94 } // chrome_browser_application_mac 95