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
15using base::HistogramBase;
16using base::HistogramSamples;
17using base::StatisticsRecorder;
18
19namespace chrome_browser_application_mac {
20
21// Generate an NSException with the given name.
22NSException* 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.
31size_t BinForExceptionNamed(NSString* name) {
32  return BinForException(ExceptionNamed(name));
33}
34
35TEST(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
49TEST(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