Index: third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp |
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp b/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp |
index 57c38183691ad9edfaac762335fedba387ec5b96..7c2e011fa6cfa35b1686f119ae2262772469f596 100644 |
--- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp |
+++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContextTest.cpp |
@@ -12,8 +12,10 @@ |
#include "core/html/HTMLMetaElement.h" |
#include "core/testing/DummyPageHolder.h" |
#include "core/testing/NullExecutionContext.h" |
+#include "platform/testing/HistogramTester.h" |
#include "platform/weborigin/KURL.h" |
#include "platform/weborigin/SecurityOrigin.h" |
+#include "public/platform/WebOriginTrialTokenStatus.h" |
#include "public/platform/WebTrialTokenValidator.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "wtf/Vector.h" |
@@ -26,42 +28,45 @@ const char kFrobulateFeatureName[] = "Frobulate"; |
const char kFrobulateEnabledOrigin[] = "https://www.example.com"; |
const char kFrobulateEnabledOriginUnsecure[] = "http://www.example.com"; |
-// Trial token which will appear valid |
-const char kGoodToken[] = "AnySignatureWillDo|https://www.example.com|Frobulate|2000000000"; |
+// Names of UMA histograms |
+const char kEnabledHistogram[] = "OriginTrials.FeatureEnabled"; |
+const char kMessageHistogram[] = "OriginTrials.FeatureEnabled.MessageGenerated"; |
+ |
+// Values for message generated histogram |
+const int kMessageHistogramValueNotRequested = 0; |
+const int kMessageHistogramValueYes = 1; |
+ |
+// Trial token placeholder for mocked calls to validator |
+const char kTokenPlaceholder[] = "The token contents are not used"; |
class MockTokenValidator : public WebTrialTokenValidator { |
public: |
MockTokenValidator() |
- : m_response(false) |
+ : m_response(WebOriginTrialTokenStatus::NotSupported) |
, m_callCount(0) |
{ |
} |
~MockTokenValidator() override {} |
// blink::WebTrialTokenValidator implementation |
- bool validateToken(const blink::WebString& token, const blink::WebSecurityOrigin& origin, const blink::WebString& featureName) override |
+ WebOriginTrialTokenStatus validateToken(const blink::WebString& token, const blink::WebSecurityOrigin& origin, const blink::WebString& featureName) override |
{ |
m_callCount++; |
return m_response; |
} |
// Useful methods for controlling the validator |
- void setResponse(bool response) |
+ void setResponse(WebOriginTrialTokenStatus response) |
{ |
m_response = response; |
} |
- void reset() |
- { |
- m_response = false; |
- m_callCount = 0; |
- } |
int callCount() |
{ |
return m_callCount; |
} |
private: |
- bool m_response; |
+ WebOriginTrialTokenStatus m_response; |
int m_callCount; |
DISALLOW_COPY_AND_ASSIGN(MockTokenValidator); |
@@ -76,6 +81,7 @@ protected: |
, m_executionContext(new NullExecutionContext()) |
, m_tokenValidator(adoptPtr(new MockTokenValidator())) |
, m_originTrialContext(new OriginTrialContext(m_executionContext.get())) |
+ , m_histogramTester(new HistogramTester()) |
{ |
RuntimeEnabledFeatures::setExperimentalFrameworkEnabled(true); |
} |
@@ -95,16 +101,39 @@ protected: |
m_executionContext->setIsSecureContext(SecurityOrigin::isSecure(pageURL)); |
} |
- bool isFeatureEnabled(const String& origin, const String& featureName, const String& token, String* errorMessage) |
+ bool isFeatureEnabled(const String& origin, const String& featureName, String* errorMessage) |
{ |
updateSecurityOrigin(origin); |
- m_originTrialContext->addToken(token); |
+ // Need at least one token to ensure the token validator is called. |
+ m_originTrialContext->addToken(kTokenPlaceholder); |
return m_originTrialContext->isFeatureEnabled(featureName, errorMessage, tokenValidator()); |
} |
- bool isFeatureEnabledWithoutErrorMessage(const String& origin, const String& featureName, const char* token) |
+ bool isFeatureEnabledWithoutErrorMessage(const String& origin, const String& featureName) |
+ { |
+ return isFeatureEnabled(origin, featureName, nullptr); |
+ } |
+ |
+ void expectEnabledUniqueMetric(WebOriginTrialTokenStatus status, int count) |
+ { |
+ m_histogramTester->expectUniqueSample( |
+ kEnabledHistogram, static_cast<int>(status), count); |
+ } |
+ |
+ void expectEnabledTotalMetric(int total) |
+ { |
+ m_histogramTester->expectTotalCount(kEnabledHistogram, total); |
+ } |
+ |
+ void expectMessageUniqueMetric(int messageGeneratedValue, int count) |
{ |
- return isFeatureEnabled(origin, featureName, token, nullptr); |
+ m_histogramTester->expectUniqueSample( |
+ kMessageHistogram, messageGeneratedValue, count); |
+ } |
+ |
+ void expectMessageTotalMetric(int total) |
+ { |
+ m_histogramTester->expectTotalCount(kMessageHistogram, total); |
} |
private: |
@@ -112,14 +141,15 @@ private: |
Persistent<NullExecutionContext> m_executionContext; |
OwnPtr<MockTokenValidator> m_tokenValidator; |
Persistent<OriginTrialContext> m_originTrialContext; |
+ std::unique_ptr<HistogramTester> m_histogramTester; |
}; |
TEST_F(OriginTrialContextTest, EnabledNonExistingFeature) |
{ |
String errorMessage; |
+ tokenValidator()->setResponse(WebOriginTrialTokenStatus::WrongFeature); |
bool isNonExistingFeatureEnabled = isFeatureEnabled(kFrobulateEnabledOrigin, |
kNonExistingFeatureName, |
- kGoodToken, |
&errorMessage); |
EXPECT_FALSE(isNonExistingFeatureEnabled); |
EXPECT_EQ(("The provided token(s) are not valid for the 'This feature does not exist' feature."), errorMessage); |
@@ -129,8 +159,7 @@ TEST_F(OriginTrialContextTest, EnabledNonExistingFeatureWithoutErrorMessage) |
{ |
bool isNonExistingFeatureEnabled = isFeatureEnabledWithoutErrorMessage( |
kFrobulateEnabledOrigin, |
- kNonExistingFeatureName, |
- kGoodToken); |
+ kNonExistingFeatureName); |
EXPECT_FALSE(isNonExistingFeatureEnabled); |
} |
@@ -138,14 +167,18 @@ TEST_F(OriginTrialContextTest, EnabledNonExistingFeatureWithoutErrorMessage) |
TEST_F(OriginTrialContextTest, EnabledSecureRegisteredOrigin) |
{ |
String errorMessage; |
- tokenValidator()->setResponse(true); |
+ tokenValidator()->setResponse(WebOriginTrialTokenStatus::Success); |
bool isOriginEnabled = isFeatureEnabled(kFrobulateEnabledOrigin, |
kFrobulateFeatureName, |
- kGoodToken, |
&errorMessage); |
EXPECT_TRUE(isOriginEnabled); |
EXPECT_TRUE(errorMessage.isEmpty()) << "Message should be empty, was: " << errorMessage; |
EXPECT_EQ(1, tokenValidator()->callCount()); |
+ |
+ // Enabled metric should be updated, but the message generated metric |
+ // should not be updated on success. |
+ expectEnabledUniqueMetric(WebOriginTrialTokenStatus::Success, 1); |
+ expectMessageTotalMetric(0); |
} |
// ... but if the browser says it's invalid for any reason, that's enough to |
@@ -153,34 +186,48 @@ TEST_F(OriginTrialContextTest, EnabledSecureRegisteredOrigin) |
TEST_F(OriginTrialContextTest, InvalidTokenResponseFromPlatform) |
{ |
String errorMessage; |
- tokenValidator()->setResponse(false); |
+ tokenValidator()->setResponse(WebOriginTrialTokenStatus::Malformed); |
bool isOriginEnabled = isFeatureEnabled(kFrobulateEnabledOrigin, |
kFrobulateFeatureName, |
- kGoodToken, |
&errorMessage); |
EXPECT_FALSE(isOriginEnabled); |
EXPECT_EQ(("The provided token(s) are not valid for the 'Frobulate' feature."), errorMessage); |
EXPECT_EQ(1, tokenValidator()->callCount()); |
+ |
+ // Enabled and message generated metrics should be updated |
+ expectEnabledUniqueMetric(WebOriginTrialTokenStatus::Malformed, 1); |
+ expectMessageUniqueMetric(kMessageHistogramValueYes, 1); |
} |
TEST_F(OriginTrialContextTest, OnlyOneErrorMessageGenerated) |
{ |
String errorMessage1; |
String errorMessage2; |
- tokenValidator()->setResponse(false); |
- isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, kGoodToken, &errorMessage1); |
- isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, kGoodToken, &errorMessage2); |
+ tokenValidator()->setResponse(WebOriginTrialTokenStatus::NotSupported); |
+ isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, &errorMessage1); |
+ |
+ // After the first call, should be one sample recorded for both the enabled |
+ // and message generated metrics |
+ expectMessageUniqueMetric(kMessageHistogramValueYes, 1); |
+ expectEnabledUniqueMetric(WebOriginTrialTokenStatus::NotSupported, 1); |
+ |
+ isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, &errorMessage2); |
EXPECT_FALSE(errorMessage1.isEmpty()); |
EXPECT_TRUE(errorMessage2.isEmpty()); |
+ |
+ // Should only be one sample recorded for the enabled metric, but two |
+ // samples for message generation. |
+ expectEnabledTotalMetric(1); |
+ expectMessageTotalMetric(2); |
} |
TEST_F(OriginTrialContextTest, ErrorMessageClearedIfStringReused) |
{ |
String errorMessage; |
- tokenValidator()->setResponse(false); |
- isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, kGoodToken, &errorMessage); |
+ tokenValidator()->setResponse(WebOriginTrialTokenStatus::NotSupported); |
+ isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, &errorMessage); |
EXPECT_FALSE(errorMessage.isEmpty()); |
- isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, kGoodToken, &errorMessage); |
+ isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, &errorMessage); |
EXPECT_TRUE(errorMessage.isEmpty()); |
} |
@@ -188,20 +235,24 @@ TEST_F(OriginTrialContextTest, ErrorMessageGeneratedPerFeature) |
{ |
String errorMessage1; |
String errorMessage2; |
- tokenValidator()->setResponse(false); |
- isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, kGoodToken, &errorMessage1); |
- isFeatureEnabled(kFrobulateEnabledOrigin, kNonExistingFeatureName, kGoodToken, &errorMessage2); |
+ tokenValidator()->setResponse(WebOriginTrialTokenStatus::NotSupported); |
+ isFeatureEnabled(kFrobulateEnabledOrigin, kFrobulateFeatureName, &errorMessage1); |
+ isFeatureEnabled(kFrobulateEnabledOrigin, kNonExistingFeatureName, &errorMessage2); |
EXPECT_FALSE(errorMessage1.isEmpty()); |
EXPECT_FALSE(errorMessage2.isEmpty()); |
+ |
+ // Enabled and message generated metrics should have same number of samples |
+ // as different features used for each call. |
+ expectEnabledUniqueMetric(WebOriginTrialTokenStatus::NotSupported, 2); |
+ expectMessageUniqueMetric(kMessageHistogramValueYes, 2); |
} |
TEST_F(OriginTrialContextTest, EnabledSecureRegisteredOriginWithoutErrorMessage) |
{ |
- tokenValidator()->setResponse(true); |
+ tokenValidator()->setResponse(WebOriginTrialTokenStatus::Success); |
bool isOriginEnabled = isFeatureEnabledWithoutErrorMessage( |
kFrobulateEnabledOrigin, |
- kFrobulateFeatureName, |
- kGoodToken); |
+ kFrobulateFeatureName); |
EXPECT_TRUE(isOriginEnabled); |
EXPECT_EQ(1, tokenValidator()->callCount()); |
} |
@@ -213,21 +264,21 @@ TEST_F(OriginTrialContextTest, EnabledNonSecureRegisteredOrigin) |
String errorMessage; |
bool isOriginEnabled = isFeatureEnabled(kFrobulateEnabledOriginUnsecure, |
kFrobulateFeatureName, |
- kGoodToken, |
&errorMessage); |
EXPECT_FALSE(isOriginEnabled); |
EXPECT_EQ(0, tokenValidator()->callCount()); |
EXPECT_FALSE(errorMessage.isEmpty()); |
+ expectEnabledUniqueMetric(WebOriginTrialTokenStatus::Insecure, 1); |
} |
TEST_F(OriginTrialContextTest, EnabledNonSecureRegisteredOriginWithoutErrorMessage) |
{ |
bool isOriginEnabled = isFeatureEnabledWithoutErrorMessage( |
kFrobulateEnabledOriginUnsecure, |
- kFrobulateFeatureName, |
- kGoodToken); |
+ kFrobulateFeatureName); |
EXPECT_FALSE(isOriginEnabled); |
EXPECT_EQ(0, tokenValidator()->callCount()); |
+ expectMessageUniqueMetric(kMessageHistogramValueNotRequested, 1); |
} |
TEST_F(OriginTrialContextTest, ParseHeaderValue) |