diff options
author | rbyers@chromium.org <rbyers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-22 21:42:15 +0000 |
---|---|---|
committer | rbyers@chromium.org <rbyers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-22 21:42:15 +0000 |
commit | b43ddb4c3b1ec6b5f59aab9968d21dd7261f8702 (patch) | |
tree | 7b1e49711a72335211c806b14f030974ed35becf /base | |
parent | 3a193c0b2a67bbe1feb9747fb243db5c92828773 (diff) | |
download | chromium_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.cc | 42 | ||||
-rw-r--r-- | base/debug/trace_event_impl.h | 4 | ||||
-rw-r--r-- | base/debug/trace_event_unittest.cc | 122 |
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 { |