summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorrbyers@chromium.org <rbyers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-22 21:42:15 +0000
committerrbyers@chromium.org <rbyers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-22 21:42:15 +0000
commitb43ddb4c3b1ec6b5f59aab9968d21dd7261f8702 (patch)
tree7b1e49711a72335211c806b14f030974ed35becf /base
parent3a193c0b2a67bbe1feb9747fb243db5c92828773 (diff)
downloadchromium_src-b43ddb4c3b1ec6b5f59aab9968d21dd7261f8702.zip
chromium_src-b43ddb4c3b1ec6b5f59aab9968d21dd7261f8702.tar.gz
chromium_src-b43ddb4c3b1ec6b5f59aab9968d21dd7261f8702.tar.bz2
Fix trace file format for NaN/infinite values
JSON doesn't support NaN/Infinity. When we get a non-finite float value we should just emit null to be consistent with JavaScript. Also removes a orphaned TraceEvent function declaration. BUG=336787 Review URL: https://codereview.chromium.org/145013003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246419 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/debug/trace_event_impl.cc42
-rw-r--r--base/debug/trace_event_impl.h4
-rw-r--r--base/debug/trace_event_unittest.cc122
3 files changed, 147 insertions, 21 deletions
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc
index a7dc8d9..abcfff1 100644
--- a/base/debug/trace_event_impl.cc
+++ b/base/debug/trace_event_impl.cc
@@ -12,6 +12,7 @@
#include "base/debug/leak_annotations.h"
#include "base/debug/trace_event.h"
#include "base/debug/trace_event_synthetic_delay.h"
+#include "base/float_util.h"
#include "base/format_macros.h"
#include "base/json/string_escape.h"
#include "base/lazy_instance.h"
@@ -635,24 +636,31 @@ void TraceEvent::AppendValueAsJSON(unsigned char type,
case TRACE_VALUE_TYPE_DOUBLE: {
// FIXME: base/json/json_writer.cc is using the same code,
// should be made into a common method.
- std::string real = DoubleToString(value.as_double);
- // Ensure that the number has a .0 if there's no decimal or 'e'. This
- // makes sure that when we read the JSON back, it's interpreted as a
- // real rather than an int.
- if (real.find('.') == std::string::npos &&
- real.find('e') == std::string::npos &&
- real.find('E') == std::string::npos) {
- real.append(".0");
- }
- // The JSON spec requires that non-integer values in the range (-1,1)
- // have a zero before the decimal point - ".52" is not valid, "0.52" is.
- if (real[0] == '.') {
- real.insert(0, "0");
- } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
- // "-.1" bad "-0.1" good
- real.insert(1, "0");
+ std::string real;
+ double val = value.as_double;
+ if (IsFinite(val)) {
+ real = DoubleToString(val);
+ // Ensure that the number has a .0 if there's no decimal or 'e'. This
+ // makes sure that when we read the JSON back, it's interpreted as a
+ // real rather than an int.
+ if (real.find('.') == std::string::npos &&
+ real.find('e') == std::string::npos &&
+ real.find('E') == std::string::npos) {
+ real.append(".0");
+ }
+ // The JSON spec requires that non-integer values in the range (-1,1)
+ // have a zero before the decimal point - ".52" is not valid, "0.52" is.
+ if (real[0] == '.') {
+ real.insert(0, "0");
+ } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
+ // "-.1" bad "-0.1" good
+ real.insert(1, "0");
+ }
+ } else {
+ // The JSON spec doesn't allow NaN and Infinity (since these are
+ // objects in EcmaScript). In practice null is substituted for them.
+ real = "null";
}
-
StringAppendF(out, "%s", real.c_str());
break;
}
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h
index f4efb7d..5e22c0e 100644
--- a/base/debug/trace_event_impl.h
+++ b/base/debug/trace_event_impl.h
@@ -125,10 +125,6 @@ class BASE_EXPORT TraceEvent {
void UpdateDuration(const TimeTicks& now, const TimeTicks& thread_now);
// Serialize event data to JSON
- static void AppendEventsAsJSON(const std::vector<TraceEvent>& events,
- size_t start,
- size_t count,
- std::string* out);
void AppendAsJSON(std::string* out) const;
void AppendPrettyPrinted(std::ostringstream* out) const;
diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc
index 1753b24..c942bc7 100644
--- a/base/debug/trace_event_unittest.cc
+++ b/base/debug/trace_event_unittest.cc
@@ -4,6 +4,7 @@
#include "base/debug/trace_event_unittest.h"
+#include <math.h>
#include <cstdlib>
#include "base/bind.h"
@@ -1988,6 +1989,127 @@ TEST_F(TraceEventTestFixture, ConvertableTypes) {
EXPECT_EQ(1, foo_val);
}
+TEST_F(TraceEventTestFixture, PrimitiveArgs) {
+ TraceLog::GetInstance()->SetEnabled(CategoryFilter("*"),
+ base::debug::TraceLog::RECORDING_MODE,
+ TraceLog::RECORD_UNTIL_FULL);
+
+ TRACE_EVENT1("foo", "event1", "int_one", 1);
+ TRACE_EVENT1("foo", "event2", "int_neg_ten", -10);
+ TRACE_EVENT1("foo", "event3", "float_one", 1.0f);
+ TRACE_EVENT1("foo", "event4", "float_half", .5f);
+ TRACE_EVENT1("foo", "event5", "float_neghalf", -.5f);
+ TRACE_EVENT1("foo", "event6", "float_infinity",
+ std::numeric_limits<float>::infinity());
+ TRACE_EVENT1("foo", "event7", "double_nan",
+ std::numeric_limits<double>::quiet_NaN());
+ void* p = 0;
+ TRACE_EVENT1("foo", "event8", "pointer_null", p);
+ p = reinterpret_cast<void*>(0xbadf00d);
+ TRACE_EVENT1("foo", "event9", "pointer_badf00d", p);
+ TRACE_EVENT1("foo", "event10", "bool_true", true);
+ TRACE_EVENT1("foo", "event11", "bool_false", false);
+ EndTraceAndFlush();
+
+ const DictionaryValue* args_dict = NULL;
+ DictionaryValue* dict = NULL;
+ const Value* value = NULL;
+ std::string str_value;
+ int int_value;
+ double double_value;
+ bool bool_value;
+
+ dict = FindNamePhase("event1", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->GetInteger("int_one", &int_value));
+ EXPECT_EQ(1, int_value);
+
+ dict = FindNamePhase("event2", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->GetInteger("int_neg_ten", &int_value));
+ EXPECT_EQ(-10, int_value);
+
+ // 1f must be serlized to JSON as "1.0" in order to be a double, not an int.
+ dict = FindNamePhase("event3", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->Get("float_one", &value));
+ EXPECT_TRUE(value->IsType(Value::TYPE_DOUBLE));
+ EXPECT_TRUE(value->GetAsDouble(&double_value));
+ EXPECT_EQ(1, double_value);
+
+ // .5f must be serlized to JSON as "0.5".
+ dict = FindNamePhase("event4", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->Get("float_half", &value));
+ EXPECT_TRUE(value->IsType(Value::TYPE_DOUBLE));
+ EXPECT_TRUE(value->GetAsDouble(&double_value));
+ EXPECT_EQ(0.5, double_value);
+
+ // -.5f must be serlized to JSON as "-0.5".
+ dict = FindNamePhase("event5", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->Get("float_neghalf", &value));
+ EXPECT_TRUE(value->IsType(Value::TYPE_DOUBLE));
+ EXPECT_TRUE(value->GetAsDouble(&double_value));
+ EXPECT_EQ(-0.5, double_value);
+
+ // Infinity can only be serlized to JSON as null.
+ dict = FindNamePhase("event6", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->Get("float_infinity", &value));
+ EXPECT_TRUE(value->IsType(Value::TYPE_NULL));
+
+ // NaN can only be serlized to JSON as null.
+ dict = FindNamePhase("event7", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->Get("double_nan", &value));
+ EXPECT_TRUE(value->IsType(Value::TYPE_NULL));
+
+ // NULL pointers should be serialized as "0x0".
+ dict = FindNamePhase("event8", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->GetString("pointer_null", &str_value));
+ EXPECT_STREQ("0x0", str_value.c_str());
+
+ // Other pointers should be serlized as a hex string.
+ dict = FindNamePhase("event9", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->GetString("pointer_badf00d", &str_value));
+ EXPECT_STREQ("0xbadf00d", str_value.c_str());
+
+ dict = FindNamePhase("event10", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->GetBoolean("bool_true", &bool_value));
+ EXPECT_TRUE(bool_value);
+
+ dict = FindNamePhase("event11", "X");
+ ASSERT_TRUE(dict);
+ dict->GetDictionary("args", &args_dict);
+ ASSERT_TRUE(args_dict);
+ EXPECT_TRUE(args_dict->GetBoolean("bool_false", &bool_value));
+ EXPECT_FALSE(bool_value);
+}
+
class TraceEventCallbackTest : public TraceEventTestFixture {
public:
virtual void SetUp() OVERRIDE {