Merge pull request #14540 from brave/issues/24529
Transition Brave Ads `StringPref`/`JSON` to `GetListPref` and `GetDictPref`
This commit is contained in:
@@ -67,9 +67,10 @@ void AdsService::RegisterProfilePrefs(
|
||||
registry->RegisterIntegerPref(ads::prefs::kIssuerPing, 7'200'000);
|
||||
registry->RegisterListPref(ads::prefs::kIssuers, base::Value::List());
|
||||
|
||||
registry->RegisterStringPref(ads::prefs::kEpsilonGreedyBanditArms, "");
|
||||
registry->RegisterStringPref(ads::prefs::kEpsilonGreedyBanditEligibleSegments,
|
||||
"");
|
||||
registry->RegisterDictionaryPref(ads::prefs::kEpsilonGreedyBanditArms,
|
||||
base::Value::Dict());
|
||||
registry->RegisterListPref(ads::prefs::kEpsilonGreedyBanditEligibleSegments,
|
||||
base::Value::List());
|
||||
|
||||
registry->RegisterTimePref(ads::prefs::kServeAdAt, base::Time());
|
||||
|
||||
|
||||
@@ -170,8 +170,6 @@ source_set("brave_ads_unit_tests") {
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/serving_features_unittest_util.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/serving_features_unittest_util.h",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/targeting/models/behavioral/bandits/epsilon_greedy_bandit_model_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/targeting/models/behavioral/bandits/epsilon_greedy_bandit_model_unittest_util.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/targeting/models/behavioral/bandits/epsilon_greedy_bandit_model_unittest_util.h",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/targeting/models/behavioral/purchase_intent/purchase_intent_model_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/targeting/models/contextual/text_classification/text_classification_model_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/ads/serving/targeting/top_segments_unittest.cc",
|
||||
@@ -371,13 +369,13 @@ source_set("brave_ads_unit_tests") {
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/anti_targeting/anti_targeting_features_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/anti_targeting/anti_targeting_resource_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/conversions/conversions_resource_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/behavioral/purchase_intent/purchase_intent_resource_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/contextual/text_classification/text_classification_resource_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/resources/resource_manager_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/segments/segment_json_reader_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/segments/segment_json_writer_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/segments/segment_util_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/segments/segment_values_util_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/server/headers/via_header_util_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/server/url/hosts/anonymous_server_host_unittest.cc",
|
||||
"//brave/vendor/bat-native-ads/src/bat/ads/internal/server/url/hosts/geo_server_host_unittest.cc",
|
||||
|
||||
Vendored
+9
-6
@@ -982,9 +982,12 @@ source_set("ads") {
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/bandit_feedback_info.h",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_info.cc",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_info.h",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms.cc",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms.h",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_util.cc",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_util.h",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_values_util.cc",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_values_util.h",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms_alias.h",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_constants.h",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_processor.cc",
|
||||
"src/bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_processor.h",
|
||||
"src/bat/ads/internal/processors/behavioral/purchase_intent/purchase_intent_processor.cc",
|
||||
@@ -1001,6 +1004,8 @@ source_set("ads") {
|
||||
"src/bat/ads/internal/resources/behavioral/anti_targeting/anti_targeting_resource.h",
|
||||
"src/bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource.cc",
|
||||
"src/bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource.h",
|
||||
"src/bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.cc",
|
||||
"src/bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.h",
|
||||
"src/bat/ads/internal/resources/behavioral/conversions/conversion_id_pattern_info.cc",
|
||||
"src/bat/ads/internal/resources/behavioral/conversions/conversion_id_pattern_info.h",
|
||||
"src/bat/ads/internal/resources/behavioral/conversions/conversions_info.cc",
|
||||
@@ -1028,12 +1033,10 @@ source_set("ads") {
|
||||
"src/bat/ads/internal/resources/resources_util.h",
|
||||
"src/bat/ads/internal/resources/resources_util_impl.h",
|
||||
"src/bat/ads/internal/segments/segment_alias.h",
|
||||
"src/bat/ads/internal/segments/segment_json_reader.cc",
|
||||
"src/bat/ads/internal/segments/segment_json_reader.h",
|
||||
"src/bat/ads/internal/segments/segment_json_writer.cc",
|
||||
"src/bat/ads/internal/segments/segment_json_writer.h",
|
||||
"src/bat/ads/internal/segments/segment_util.cc",
|
||||
"src/bat/ads/internal/segments/segment_util.h",
|
||||
"src/bat/ads/internal/segments/segment_values_util.cc",
|
||||
"src/bat/ads/internal/segments/segment_values_util.h",
|
||||
"src/bat/ads/internal/server/headers/via_header_util.cc",
|
||||
"src/bat/ads/internal/server/headers/via_header_util.h",
|
||||
"src/bat/ads/internal/server/url/hosts/anonymous_server_host.cc",
|
||||
|
||||
+9
-22
@@ -12,12 +12,11 @@
|
||||
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/rand_util.h"
|
||||
#include "bat/ads/internal/ads_client_helper.h"
|
||||
#include "bat/ads/internal/base/logging_util.h"
|
||||
#include "bat/ads/internal/features/epsilon_greedy_bandit_features.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms.h"
|
||||
#include "bat/ads/internal/segments/segment_json_reader.h"
|
||||
#include "bat/ads/pref_names.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_util.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms_alias.h"
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.h"
|
||||
|
||||
namespace ads {
|
||||
namespace targeting {
|
||||
@@ -69,25 +68,19 @@ ArmBucketMap BucketSortArms(const ArmList& arms) {
|
||||
return buckets;
|
||||
}
|
||||
|
||||
SegmentList GetEligibleSegments() {
|
||||
const std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditEligibleSegments);
|
||||
|
||||
return JSONReader::ReadSegments(json);
|
||||
}
|
||||
|
||||
EpsilonGreedyBanditArmMap GetEligibleArms(
|
||||
const EpsilonGreedyBanditArmMap& arms) {
|
||||
const SegmentList eligible_segments = GetEligibleSegments();
|
||||
if (eligible_segments.empty()) {
|
||||
const SegmentList segments =
|
||||
resource::GetEpsilonGreedyBanditEligibleSegments();
|
||||
if (segments.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
EpsilonGreedyBanditArmMap eligible_arms;
|
||||
|
||||
for (const auto& arm : arms) {
|
||||
if (std::find(eligible_segments.cbegin(), eligible_segments.cend(),
|
||||
arm.first) == eligible_segments.end()) {
|
||||
if (std::find(segments.cbegin(), segments.cend(), arm.first) ==
|
||||
segments.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -192,13 +185,7 @@ EpsilonGreedyBandit::EpsilonGreedyBandit() = default;
|
||||
EpsilonGreedyBandit::~EpsilonGreedyBandit() = default;
|
||||
|
||||
SegmentList EpsilonGreedyBandit::GetSegments() const {
|
||||
const std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
|
||||
const EpsilonGreedyBanditArmMap arms =
|
||||
EpsilonGreedyBanditArms::FromJson(json);
|
||||
|
||||
return GetSegmentsForArms(arms);
|
||||
return GetSegmentsForArms(GetEpsilonGreedyBanditArms());
|
||||
}
|
||||
|
||||
} // namespace model
|
||||
|
||||
+9
-9
@@ -9,13 +9,14 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "bat/ads/internal/ads/serving/targeting/models/behavioral/bandits/epsilon_greedy_bandit_model_unittest_util.h"
|
||||
#include "bat/ads/internal/base/unittest/unittest_base.h"
|
||||
#include "bat/ads/internal/features/epsilon_greedy_bandit_features.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/bandit_feedback_info.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_constants.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_processor.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_segments.h"
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource.h"
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.h"
|
||||
#include "bat/ads/internal/segments/segment_util.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BatAds*
|
||||
|
||||
@@ -33,7 +34,7 @@ class BatAdsEpsilonGreedyBanditModelTest : public UnitTestBase {
|
||||
TEST_F(BatAdsEpsilonGreedyBanditModelTest,
|
||||
GetSegmentsIfProcessorNeverInitialized) {
|
||||
// Arrange
|
||||
SaveAllSegments();
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
// Act
|
||||
EpsilonGreedyBandit model;
|
||||
@@ -61,7 +62,7 @@ TEST_F(BatAdsEpsilonGreedyBanditModelTest, EligableSegmentsAreEmpty) {
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditModelTest, GetSegmentsIfNeverProcessed) {
|
||||
// Arrange
|
||||
SaveAllSegments();
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitAndEnableFeatureWithParameters(
|
||||
@@ -79,7 +80,7 @@ TEST_F(BatAdsEpsilonGreedyBanditModelTest, GetSegmentsIfNeverProcessed) {
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditModelTest, GetSegmentsForExploration) {
|
||||
// Arrange
|
||||
SaveAllSegments();
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitAndEnableFeatureWithParameters(
|
||||
@@ -103,7 +104,7 @@ TEST_F(BatAdsEpsilonGreedyBanditModelTest, GetSegmentsForExploration) {
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditModelTest, GetSegmentsForExploitation) {
|
||||
// Arrange
|
||||
SaveAllSegments();
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitAndEnableFeatureWithParameters(
|
||||
@@ -144,9 +145,8 @@ TEST_F(BatAdsEpsilonGreedyBanditModelTest, GetSegmentsForExploitation) {
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditModelTest, GetSegmentsForEligibleSegments) {
|
||||
// Arrange
|
||||
const std::vector<std::string> eligible_segments = {
|
||||
"science", "technology & computing", "invalid_segment"};
|
||||
SaveSegments(eligible_segments);
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(
|
||||
{"science", "technology & computing", "invalid_segment"});
|
||||
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitAndEnableFeatureWithParameters(
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/ads/serving/targeting/models/behavioral/bandits/epsilon_greedy_bandit_model_unittest_util.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "bat/ads/internal/ads_client_helper.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_segments.h"
|
||||
#include "bat/ads/internal/segments/segment_json_writer.h"
|
||||
#include "bat/ads/pref_names.h"
|
||||
|
||||
namespace ads {
|
||||
namespace targeting {
|
||||
namespace model {
|
||||
|
||||
void SaveSegments(const SegmentList& segments) {
|
||||
const std::string json = JSONWriter::WriteSegments(segments);
|
||||
|
||||
AdsClientHelper::GetInstance()->SetStringPref(
|
||||
prefs::kEpsilonGreedyBanditEligibleSegments, json);
|
||||
}
|
||||
|
||||
void SaveAllSegments() {
|
||||
SaveSegments(kSegments);
|
||||
}
|
||||
|
||||
} // namespace model
|
||||
} // namespace targeting
|
||||
} // namespace ads
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_ADS_SERVING_TARGETING_MODELS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_MODEL_UNITTEST_UTIL_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_ADS_SERVING_TARGETING_MODELS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_MODEL_UNITTEST_UTIL_H_
|
||||
|
||||
#include "bat/ads/internal/segments/segment_alias.h"
|
||||
|
||||
namespace ads {
|
||||
namespace targeting {
|
||||
namespace model {
|
||||
|
||||
void SaveSegments(const SegmentList& segments);
|
||||
|
||||
void SaveAllSegments();
|
||||
|
||||
} // namespace model
|
||||
} // namespace targeting
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_ADS_SERVING_TARGETING_MODELS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_MODEL_UNITTEST_UTIL_H_
|
||||
+6
-5
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "bat/ads/internal/ads/serving/targeting/models/behavioral/bandits/epsilon_greedy_bandit_model_unittest_util.h"
|
||||
#include "bat/ads/internal/ads/serving/targeting/user_model_builder.h"
|
||||
#include "bat/ads/internal/ads/serving/targeting/user_model_info.h"
|
||||
#include "bat/ads/internal/base/unittest/unittest_base.h"
|
||||
@@ -21,13 +20,15 @@
|
||||
#include "bat/ads/internal/features/purchase_intent_features.h"
|
||||
#include "bat/ads/internal/features/text_classification_features.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/bandit_feedback_info.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_constants.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_processor.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_segments.h"
|
||||
#include "bat/ads/internal/processors/behavioral/purchase_intent/purchase_intent_processor.h"
|
||||
#include "bat/ads/internal/processors/contextual/text_classification/text_classification_processor.h"
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource.h"
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.h"
|
||||
#include "bat/ads/internal/resources/behavioral/purchase_intent/purchase_intent_resource.h"
|
||||
#include "bat/ads/internal/resources/contextual/text_classification/text_classification_resource.h"
|
||||
#include "bat/ads/internal/segments/segment_util.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BatAds*
|
||||
@@ -154,7 +155,7 @@ class BatAdsTopSegmentsTest
|
||||
|
||||
TEST_P(BatAdsTopSegmentsTest, GetSegments) {
|
||||
// Arrange
|
||||
model::SaveAllSegments();
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
ModelCombinationsParamInfo param(GetParam());
|
||||
if (param.previously_processed) {
|
||||
@@ -234,7 +235,7 @@ INSTANTIATE_TEST_SUITE_P(BatAdsTopSegmentsTest,
|
||||
|
||||
TEST_F(BatAdsTopSegmentsTest, GetSegmentsForAllModelsIfPreviouslyProcessed) {
|
||||
// Arrange
|
||||
model::SaveAllSegments();
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
ProcessBandit();
|
||||
ProcessTextClassification();
|
||||
@@ -272,7 +273,7 @@ TEST_F(BatAdsTopSegmentsTest, GetSegmentsForAllModelsIfPreviouslyProcessed) {
|
||||
|
||||
TEST_F(BatAdsTopSegmentsTest, GetSegmentsForFieldTrialParticipationPath) {
|
||||
// Arrange
|
||||
model::SaveAllSegments();
|
||||
resource::SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
ProcessBandit();
|
||||
ProcessTextClassification();
|
||||
|
||||
@@ -297,6 +297,11 @@ void UnitTestBase::SetDefaultPrefs() {
|
||||
ads_client_mock_->SetInt64Pref(prefs::kIssuerPing, 0);
|
||||
ads_client_mock_->SetListPref(prefs::kIssuers, base::Value::List());
|
||||
|
||||
ads_client_mock_->SetDictPref(prefs::kEpsilonGreedyBanditArms,
|
||||
base::Value::Dict());
|
||||
ads_client_mock_->SetListPref(prefs::kEpsilonGreedyBanditEligibleSegments,
|
||||
base::Value::List());
|
||||
|
||||
ads_client_mock_->SetTimePref(prefs::kServeAdAt, Now());
|
||||
|
||||
ads_client_mock_->SetTimePref(prefs::kNextTokenRedemptionAt, DistantFuture());
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_util.h"
|
||||
|
||||
#include "base/values.h"
|
||||
#include "bat/ads/internal/ads_client_helper.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_values_util.h"
|
||||
#include "bat/ads/pref_names.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
namespace ads {
|
||||
namespace targeting {
|
||||
|
||||
void SetEpsilonGreedyBanditArms(const EpsilonGreedyBanditArmMap& arms) {
|
||||
AdsClientHelper::GetInstance()->SetDictPref(
|
||||
prefs::kEpsilonGreedyBanditArms, EpsilonGreedyBanditArmsToValue(arms));
|
||||
}
|
||||
|
||||
EpsilonGreedyBanditArmMap GetEpsilonGreedyBanditArms() {
|
||||
const absl::optional<base::Value::Dict> dict =
|
||||
AdsClientHelper::GetInstance()->GetDictPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
if (!dict) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return EpsilonGreedyBanditArmsFromValue(*dict);
|
||||
}
|
||||
|
||||
} // namespace targeting
|
||||
} // namespace ads
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARM_UTIL_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARM_UTIL_H_
|
||||
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms_alias.h"
|
||||
|
||||
namespace ads {
|
||||
namespace targeting {
|
||||
|
||||
void SetEpsilonGreedyBanditArms(const EpsilonGreedyBanditArmMap& arms);
|
||||
EpsilonGreedyBanditArmMap GetEpsilonGreedyBanditArms();
|
||||
|
||||
} // namespace targeting
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARM_UTIL_H_
|
||||
+48
-54
@@ -1,16 +1,14 @@
|
||||
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_values_util.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/values.h"
|
||||
#include "bat/ads/internal/base/logging_util.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
@@ -23,67 +21,40 @@ constexpr char kSegmentKey[] = "segment";
|
||||
constexpr char kValueKey[] = "value";
|
||||
constexpr char kPullsKey[] = "pulls";
|
||||
|
||||
bool GetArmFromDictionary(const base::Value::Dict& dict,
|
||||
EpsilonGreedyBanditArmInfo* info) {
|
||||
DCHECK(info);
|
||||
|
||||
EpsilonGreedyBanditArmInfo arm;
|
||||
absl::optional<EpsilonGreedyBanditArmInfo> MaybeGetArmFromDict(
|
||||
const base::Value::Dict& dict) {
|
||||
const std::string* segment = dict.FindString(kSegmentKey);
|
||||
if (!segment || segment->empty()) {
|
||||
return false;
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
EpsilonGreedyBanditArmInfo arm;
|
||||
arm.segment = *segment;
|
||||
arm.pulls = dict.FindInt(kPullsKey).value_or(0);
|
||||
arm.value = dict.FindDouble(kValueKey).value_or(1.0);
|
||||
*info = arm;
|
||||
return true;
|
||||
|
||||
return arm;
|
||||
}
|
||||
|
||||
EpsilonGreedyBanditArmMap GetArmsFromDictionary(const base::Value::Dict& dict) {
|
||||
EpsilonGreedyBanditArmMap arms;
|
||||
bool found_errors = false;
|
||||
for (const auto [key, value] : dict) {
|
||||
if (!value.is_dict()) {
|
||||
found_errors = true;
|
||||
continue;
|
||||
}
|
||||
const base::Value::Dict& arm_dict = value.GetDict();
|
||||
|
||||
EpsilonGreedyBanditArmInfo arm;
|
||||
if (!GetArmFromDictionary(arm_dict, &arm)) {
|
||||
found_errors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
arms[key] = arm;
|
||||
absl::optional<EpsilonGreedyBanditArmInfo> MaybeGetArmFromValue(
|
||||
const base::Value& value) {
|
||||
const base::Value::Dict* dict = value.GetIfDict();
|
||||
if (!dict) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
if (found_errors) {
|
||||
BLOG(0, "Errors detected when parsing epsilon greedy bandit arms");
|
||||
const absl::optional<EpsilonGreedyBanditArmInfo> arm =
|
||||
MaybeGetArmFromDict(*dict);
|
||||
if (!arm) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
return arms;
|
||||
|
||||
return arm;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EpsilonGreedyBanditArms::EpsilonGreedyBanditArms() = default;
|
||||
|
||||
EpsilonGreedyBanditArms::~EpsilonGreedyBanditArms() = default;
|
||||
|
||||
EpsilonGreedyBanditArmMap EpsilonGreedyBanditArms::FromJson(
|
||||
const std::string& json) {
|
||||
EpsilonGreedyBanditArmMap arms;
|
||||
absl::optional<base::Value> value = base::JSONReader::Read(json);
|
||||
if (!value || !value->is_dict()) {
|
||||
return arms;
|
||||
}
|
||||
const base::Value::Dict& arm_dict = value->GetDict();
|
||||
|
||||
arms = GetArmsFromDictionary(arm_dict);
|
||||
return arms;
|
||||
}
|
||||
|
||||
std::string EpsilonGreedyBanditArms::ToJson(
|
||||
base::Value::Dict EpsilonGreedyBanditArmsToValue(
|
||||
const EpsilonGreedyBanditArmMap& arms) {
|
||||
base::Value::Dict dict;
|
||||
|
||||
@@ -92,12 +63,35 @@ std::string EpsilonGreedyBanditArms::ToJson(
|
||||
item.Set(kSegmentKey, key);
|
||||
item.Set(kPullsKey, value.pulls);
|
||||
item.Set(kValueKey, value.value);
|
||||
|
||||
dict.Set(key, std::move(item));
|
||||
}
|
||||
|
||||
std::string json;
|
||||
base::JSONWriter::Write(dict, &json);
|
||||
return json;
|
||||
return dict;
|
||||
}
|
||||
|
||||
EpsilonGreedyBanditArmMap EpsilonGreedyBanditArmsFromValue(
|
||||
const base::Value::Dict& dict) {
|
||||
bool found_errors = false;
|
||||
|
||||
EpsilonGreedyBanditArmMap arms;
|
||||
|
||||
for (const auto [key, value] : dict) {
|
||||
const absl::optional<EpsilonGreedyBanditArmInfo> arm =
|
||||
MaybeGetArmFromValue(value);
|
||||
if (!arm) {
|
||||
found_errors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
arms[key] = *arm;
|
||||
}
|
||||
|
||||
if (found_errors) {
|
||||
BLOG(0, "Error parsing epsilon greedy bandit arms");
|
||||
}
|
||||
|
||||
return arms;
|
||||
}
|
||||
|
||||
} // namespace targeting
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARM_VALUES_UTIL_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARM_VALUES_UTIL_H_
|
||||
|
||||
#include "base/values.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms_alias.h"
|
||||
|
||||
namespace ads {
|
||||
namespace targeting {
|
||||
|
||||
base::Value::Dict EpsilonGreedyBanditArmsToValue(
|
||||
const EpsilonGreedyBanditArmMap& arms);
|
||||
EpsilonGreedyBanditArmMap EpsilonGreedyBanditArmsFromValue(
|
||||
const base::Value::Dict& dict);
|
||||
|
||||
} // namespace targeting
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARM_VALUES_UTIL_H_
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARMS_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARMS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms_alias.h"
|
||||
|
||||
namespace ads {
|
||||
namespace targeting {
|
||||
|
||||
class EpsilonGreedyBanditArms final {
|
||||
public:
|
||||
EpsilonGreedyBanditArms();
|
||||
~EpsilonGreedyBanditArms();
|
||||
EpsilonGreedyBanditArms(const EpsilonGreedyBanditArms&) = delete;
|
||||
EpsilonGreedyBanditArms& operator=(const EpsilonGreedyBanditArms&) = delete;
|
||||
|
||||
static EpsilonGreedyBanditArmMap FromJson(const std::string& json);
|
||||
static std::string ToJson(const EpsilonGreedyBanditArmMap& arms);
|
||||
};
|
||||
|
||||
} // namespace targeting
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_ARMS_H_
|
||||
+3
-3
@@ -3,8 +3,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_SEGMENTS_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_SEGMENTS_H_
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_CONSTANTS_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_CONSTANTS_H_
|
||||
|
||||
#include "bat/ads/internal/segments/segment_alias.h"
|
||||
|
||||
@@ -45,4 +45,4 @@ const SegmentList kSegments = {"architecture",
|
||||
} // namespace targeting
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_SEGMENTS_H_
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_CONSTANTS_H_
|
||||
+18
-27
@@ -7,23 +7,24 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/notreached.h"
|
||||
#include "bat/ads/internal/ads_client_helper.h"
|
||||
#include "bat/ads/internal/base/logging_util.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/bandit_feedback_info.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_segments.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_info.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_util.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_values_util.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms_alias.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_constants.h"
|
||||
#include "bat/ads/internal/segments/segment_util.h"
|
||||
#include "bat/ads/pref_names.h"
|
||||
|
||||
namespace ads {
|
||||
namespace processor {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr double kArmDefaultValue = 1.0;
|
||||
constexpr uint64_t kArmDefaultPulls = 0;
|
||||
constexpr double kDefaultArmValue = 1.0;
|
||||
constexpr int kDefaultArmPulls = 0;
|
||||
|
||||
targeting::EpsilonGreedyBanditArmMap MaybeAddOrResetArms(
|
||||
const targeting::EpsilonGreedyBanditArmMap& arms) {
|
||||
@@ -42,8 +43,8 @@ targeting::EpsilonGreedyBanditArmMap MaybeAddOrResetArms(
|
||||
}
|
||||
|
||||
targeting::EpsilonGreedyBanditArmInfo arm;
|
||||
arm.value = kArmDefaultValue;
|
||||
arm.pulls = kArmDefaultPulls;
|
||||
arm.value = kDefaultArmValue;
|
||||
arm.pulls = kDefaultArmPulls;
|
||||
|
||||
updated_arms[segment] = arm;
|
||||
|
||||
@@ -117,31 +118,22 @@ void EpsilonGreedyBandit::Process(const BanditFeedbackInfo& feedback) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EpsilonGreedyBandit::InitializeArms() const {
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
|
||||
arms = MaybeAddOrResetArms(arms);
|
||||
|
||||
arms = MaybeDeleteArms(arms);
|
||||
|
||||
json = targeting::EpsilonGreedyBanditArms::ToJson(arms);
|
||||
AdsClientHelper::GetInstance()->SetStringPref(prefs::kEpsilonGreedyBanditArms,
|
||||
json);
|
||||
targeting::SetEpsilonGreedyBanditArms(arms);
|
||||
|
||||
BLOG(1, "Successfully initialized epsilon greedy bandit arms");
|
||||
}
|
||||
|
||||
void EpsilonGreedyBandit::UpdateArm(const uint64_t reward,
|
||||
void EpsilonGreedyBandit::UpdateArm(const int reward,
|
||||
const std::string& segment) const {
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
if (arms.empty()) {
|
||||
BLOG(1, "No epsilon greedy bandit arms");
|
||||
return;
|
||||
@@ -156,13 +148,12 @@ void EpsilonGreedyBandit::UpdateArm(const uint64_t reward,
|
||||
|
||||
targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
arm.pulls++;
|
||||
arm.value = arm.value + (1.0 / arm.pulls * (reward - arm.value));
|
||||
DCHECK_NE(0, arm.pulls);
|
||||
arm.value =
|
||||
arm.value + (1.0 / arm.pulls * (static_cast<double>(reward) - arm.value));
|
||||
iter->second = arm;
|
||||
|
||||
json = targeting::EpsilonGreedyBanditArms::ToJson(arms);
|
||||
|
||||
AdsClientHelper::GetInstance()->SetStringPref(prefs::kEpsilonGreedyBanditArms,
|
||||
json);
|
||||
targeting::SetEpsilonGreedyBanditArms(arms);
|
||||
|
||||
BLOG(1,
|
||||
"Epsilon greedy bandit arm was updated for " << segment << " segment");
|
||||
|
||||
+1
-2
@@ -6,7 +6,6 @@
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_PROCESSOR_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_PROCESSORS_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_PROCESSOR_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace ads {
|
||||
@@ -26,7 +25,7 @@ class EpsilonGreedyBandit final {
|
||||
private:
|
||||
void InitializeArms() const;
|
||||
|
||||
void UpdateArm(const uint64_t reward, const std::string& segment) const;
|
||||
void UpdateArm(const int reward, const std::string& segment) const;
|
||||
};
|
||||
|
||||
} // namespace processor
|
||||
|
||||
+81
-87
@@ -5,26 +5,12 @@
|
||||
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_processor.h"
|
||||
|
||||
#include "bat/ads/internal/ads_client_helper.h"
|
||||
#include "bat/ads/internal/base/containers/container_util.h"
|
||||
#include "bat/ads/internal/base/unittest/unittest_base.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/bandit_feedback_info.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arms.h"
|
||||
#include "bat/ads/pref_names.h"
|
||||
#include "bat/ads/internal/processors/behavioral/bandits/epsilon_greedy_bandit_arm_util.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BatAds*
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kArmsWithEmptySegmentJson[] = R"(
|
||||
{
|
||||
"travel":{"pulls":0,"segment":"travel","value":1.0},
|
||||
"":{"pulls":0,"segment":"","value":1.0}
|
||||
}
|
||||
)";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace ads {
|
||||
|
||||
class BatAdsEpsilonGreedyBanditProcessorTest : public UnitTestBase {
|
||||
@@ -34,50 +20,52 @@ class BatAdsEpsilonGreedyBanditProcessorTest : public UnitTestBase {
|
||||
~BatAdsEpsilonGreedyBanditProcessorTest() override = default;
|
||||
};
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest, InitializeAllArmsFromResource) {
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest, InitializeArmsFromResource) {
|
||||
// Arrange
|
||||
targeting::EpsilonGreedyBanditArmMap prefs_arms;
|
||||
targeting::EpsilonGreedyBanditArmInfo prefs_arm_info;
|
||||
prefs_arm_info.segment = "foo";
|
||||
prefs_arms["foo"] = prefs_arm_info;
|
||||
prefs_arm_info.segment = "bar";
|
||||
prefs_arms["bar"] = prefs_arm_info;
|
||||
{
|
||||
targeting::EpsilonGreedyBanditArmMap arms;
|
||||
|
||||
AdsClientHelper::GetInstance()->SetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms,
|
||||
targeting::EpsilonGreedyBanditArms::ToJson(prefs_arms));
|
||||
targeting::EpsilonGreedyBanditArmInfo arm_1;
|
||||
arm_1.segment = "foo";
|
||||
arm_1.pulls = 0;
|
||||
arm_1.value = 1.0;
|
||||
arms["foo"] = arm_1;
|
||||
|
||||
targeting::EpsilonGreedyBanditArmInfo arm_2;
|
||||
arm_2.segment = "bar";
|
||||
arm_2.pulls = 0;
|
||||
arm_2.value = 1.0;
|
||||
arms["bar"] = arm_2;
|
||||
|
||||
targeting::SetEpsilonGreedyBanditArms(arms);
|
||||
}
|
||||
|
||||
// Act
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
|
||||
// Assert
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
|
||||
EXPECT_EQ(30U, arms.size());
|
||||
|
||||
EXPECT_EQ(0u, arms.count("foo"));
|
||||
EXPECT_EQ(0u, arms.count("bar"));
|
||||
EXPECT_EQ(0U, arms.count("foo"));
|
||||
EXPECT_EQ(0U, arms.count("bar"));
|
||||
}
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest, NeverProcessed) {
|
||||
// Arrange
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
const std::string segment = "travel"; // rewards: [] => value: 1.0
|
||||
|
||||
// Act
|
||||
// rewards: [] => value: 1.0
|
||||
std::string segment = "travel";
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
|
||||
// Assert
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
const auto iter = arms.find(segment);
|
||||
ASSERT_TRUE(iter != arms.end());
|
||||
const targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
|
||||
auto iter = arms.find(segment);
|
||||
targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
targeting::EpsilonGreedyBanditArmInfo expected_arm;
|
||||
expected_arm.segment = segment;
|
||||
expected_arm.value = 1.0;
|
||||
@@ -89,24 +77,22 @@ TEST_F(BatAdsEpsilonGreedyBanditProcessorTest, NeverProcessed) {
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest,
|
||||
ProcessSegmentFourTimesWithOneReward) {
|
||||
// Arrange
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
const std::string segment = "travel"; // rewards: [0, 0, 0, 0] => value: 0.0
|
||||
|
||||
// Act
|
||||
// rewards: [0, 0, 0, 0] => value: 0.0
|
||||
std::string segment = "travel";
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kDismissed});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kDismissed});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kTimedOut});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kDismissed});
|
||||
|
||||
// Assert
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
const auto iter = arms.find(segment);
|
||||
ASSERT_TRUE(iter != arms.end());
|
||||
const targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
|
||||
auto iter = arms.find(segment);
|
||||
targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
targeting::EpsilonGreedyBanditArmInfo expected_arm;
|
||||
expected_arm.segment = segment;
|
||||
expected_arm.value = 0.0;
|
||||
@@ -118,24 +104,22 @@ TEST_F(BatAdsEpsilonGreedyBanditProcessorTest,
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest,
|
||||
ProcessSegmentFourTimesWithTwoRewards) {
|
||||
// Arrange
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
const std::string segment = "travel"; // rewards: [1, 0, 1, 0] => value: 0.5
|
||||
|
||||
// Act
|
||||
// rewards: [1, 0, 1, 0] => value: 0.5
|
||||
std::string segment = "travel";
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kClicked});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kDismissed});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kClicked});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kTimedOut});
|
||||
|
||||
// Assert
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
const auto iter = arms.find(segment);
|
||||
ASSERT_TRUE(iter != arms.end());
|
||||
const targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
|
||||
auto iter = arms.find(segment);
|
||||
targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
targeting::EpsilonGreedyBanditArmInfo expected_arm;
|
||||
expected_arm.segment = segment;
|
||||
expected_arm.value = 0.5;
|
||||
@@ -147,24 +131,22 @@ TEST_F(BatAdsEpsilonGreedyBanditProcessorTest,
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest,
|
||||
ProcessSegmentFourTimesWithFourRewards) {
|
||||
// Arrange
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
const std::string segment = "travel"; // rewards: [1, 1, 1, 1] => value: 1.0
|
||||
|
||||
// Act
|
||||
// rewards: [1, 1, 1, 1] => value: 1.0
|
||||
std::string segment = "travel";
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kClicked});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kClicked});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kClicked});
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kClicked});
|
||||
|
||||
// Assert
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
const auto iter = arms.find(segment);
|
||||
ASSERT_TRUE(iter != arms.end());
|
||||
const targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
|
||||
auto iter = arms.find(segment);
|
||||
targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
targeting::EpsilonGreedyBanditArmInfo expected_arm;
|
||||
expected_arm.segment = segment;
|
||||
expected_arm.value = 1.0;
|
||||
@@ -175,39 +157,35 @@ TEST_F(BatAdsEpsilonGreedyBanditProcessorTest,
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest, ProcessSegmentNotInResource) {
|
||||
// Arrange
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
const std::string segment = "foobar";
|
||||
|
||||
// Act
|
||||
std::string segment = "foobar";
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kTimedOut});
|
||||
|
||||
// Assert
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
|
||||
auto iter = arms.find(segment);
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
const auto iter = arms.find(segment);
|
||||
EXPECT_TRUE(iter == arms.end());
|
||||
}
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest, ProcessChildSegment) {
|
||||
// Arrange
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
const std::string segment = "travel-child";
|
||||
const std::string parent_segment = "travel";
|
||||
|
||||
// Act
|
||||
std::string segment = "travel-child";
|
||||
std::string parent_segment = "travel";
|
||||
processor::EpsilonGreedyBandit processor;
|
||||
processor.Process({segment, mojom::NotificationAdEventType::kTimedOut});
|
||||
|
||||
// Assert
|
||||
std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditArms);
|
||||
targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(json);
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
const auto iter = arms.find(parent_segment);
|
||||
ASSERT_TRUE(iter != arms.end());
|
||||
const targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
|
||||
auto iter = arms.find(parent_segment);
|
||||
targeting::EpsilonGreedyBanditArmInfo arm = iter->second;
|
||||
targeting::EpsilonGreedyBanditArmInfo expected_arm;
|
||||
expected_arm.segment = parent_segment;
|
||||
expected_arm.value = 0.0;
|
||||
@@ -219,13 +197,29 @@ TEST_F(BatAdsEpsilonGreedyBanditProcessorTest, ProcessChildSegment) {
|
||||
TEST_F(BatAdsEpsilonGreedyBanditProcessorTest,
|
||||
InitializeArmsFromResourceWithEmptySegments) {
|
||||
// Arrange
|
||||
{
|
||||
targeting::EpsilonGreedyBanditArmMap arms;
|
||||
|
||||
targeting::EpsilonGreedyBanditArmInfo arm_1;
|
||||
arm_1.segment = "travel";
|
||||
arm_1.pulls = 0;
|
||||
arm_1.value = 1.0;
|
||||
arms["travel"] = arm_1;
|
||||
|
||||
targeting::EpsilonGreedyBanditArmInfo arm_2;
|
||||
arm_2.segment = "";
|
||||
arm_2.pulls = 0;
|
||||
arm_2.value = 1.0;
|
||||
arms[""] = arm_2;
|
||||
|
||||
targeting::SetEpsilonGreedyBanditArms(arms);
|
||||
}
|
||||
|
||||
// Act
|
||||
const targeting::EpsilonGreedyBanditArmMap arms =
|
||||
targeting::EpsilonGreedyBanditArms::FromJson(kArmsWithEmptySegmentJson);
|
||||
targeting::GetEpsilonGreedyBanditArms();
|
||||
|
||||
// Assert
|
||||
// Empty segments are skipped.
|
||||
EXPECT_EQ(1U, arms.size());
|
||||
EXPECT_EQ(1U, arms.count("travel"));
|
||||
}
|
||||
|
||||
+4
-22
@@ -5,32 +5,16 @@
|
||||
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "bat/ads/internal/ads_client_helper.h"
|
||||
#include "bat/ads/internal/base/logging_util.h"
|
||||
#include "bat/ads/internal/catalog/catalog.h"
|
||||
#include "bat/ads/internal/catalog/catalog_info.h"
|
||||
#include "bat/ads/internal/segments/segment_json_reader.h"
|
||||
#include "bat/ads/internal/segments/segment_json_writer.h"
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.h"
|
||||
#include "bat/ads/internal/segments/segment_util.h"
|
||||
#include "bat/ads/pref_names.h"
|
||||
|
||||
namespace ads {
|
||||
namespace resource {
|
||||
|
||||
namespace {
|
||||
|
||||
SegmentList GetSegments() {
|
||||
const std::string json = AdsClientHelper::GetInstance()->GetStringPref(
|
||||
prefs::kEpsilonGreedyBanditEligibleSegments);
|
||||
|
||||
return JSONReader::ReadSegments(json);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EpsilonGreedyBandit::EpsilonGreedyBandit(Catalog* catalog) : catalog_(catalog) {
|
||||
DCHECK(catalog_);
|
||||
|
||||
@@ -48,21 +32,19 @@ bool EpsilonGreedyBandit::IsInitialized() const {
|
||||
void EpsilonGreedyBandit::LoadFromCatalog(const CatalogInfo& catalog) {
|
||||
const SegmentList segments = GetSegments(catalog);
|
||||
const SegmentList parent_segments = GetParentSegments(segments);
|
||||
const std::string json = JSONWriter::WriteSegments(parent_segments);
|
||||
|
||||
AdsClientHelper::GetInstance()->SetStringPref(
|
||||
prefs::kEpsilonGreedyBanditEligibleSegments, json);
|
||||
|
||||
BLOG(2, "Successfully loaded epsilon greedy bandit segments:");
|
||||
for (const auto& segment : parent_segments) {
|
||||
BLOG(2, " " << segment);
|
||||
}
|
||||
|
||||
SetEpsilonGreedyBanditEligibleSegments(parent_segments);
|
||||
|
||||
is_initialized_ = true;
|
||||
}
|
||||
|
||||
SegmentList EpsilonGreedyBandit::Get() const {
|
||||
return GetSegments();
|
||||
return GetEpsilonGreedyBanditEligibleSegments();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.h"
|
||||
|
||||
#include "base/values.h"
|
||||
#include "bat/ads/internal/ads_client_helper.h"
|
||||
#include "bat/ads/internal/segments/segment_values_util.h"
|
||||
#include "bat/ads/pref_names.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
namespace ads {
|
||||
namespace resource {
|
||||
|
||||
void SetEpsilonGreedyBanditEligibleSegments(const SegmentList& segments) {
|
||||
AdsClientHelper::GetInstance()->SetListPref(
|
||||
prefs::kEpsilonGreedyBanditEligibleSegments, SegmentsToValue(segments));
|
||||
}
|
||||
|
||||
SegmentList GetEpsilonGreedyBanditEligibleSegments() {
|
||||
const absl::optional<base::Value::List> list =
|
||||
AdsClientHelper::GetInstance()->GetListPref(
|
||||
prefs::kEpsilonGreedyBanditEligibleSegments);
|
||||
if (!list) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return SegmentsFromValue(*list);
|
||||
}
|
||||
|
||||
} // namespace resource
|
||||
} // namespace ads
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_RESOURCES_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_RESOURCE_UTIL_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_RESOURCES_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_RESOURCE_UTIL_H_
|
||||
|
||||
#include "bat/ads/internal/segments/segment_alias.h"
|
||||
|
||||
namespace ads {
|
||||
namespace resource {
|
||||
|
||||
void SetEpsilonGreedyBanditEligibleSegments(const SegmentList& segments);
|
||||
SegmentList GetEpsilonGreedyBanditEligibleSegments();
|
||||
|
||||
} // namespace resource
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_RESOURCES_BEHAVIORAL_BANDITS_EPSILON_GREEDY_BANDIT_RESOURCE_UTIL_H_
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/resources/behavioral/bandits/epsilon_greedy_bandit_resource_util.h"
|
||||
|
||||
#include "bat/ads/internal/base/unittest/unittest_base.h"
|
||||
#include "bat/ads/internal/segments/segment_alias.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BatAds*
|
||||
|
||||
namespace ads {
|
||||
namespace resource {
|
||||
|
||||
namespace {
|
||||
const SegmentList kSegments = {"foo", "bar"};
|
||||
} // namespace
|
||||
|
||||
class BatAdsEpsilonGreedyBanditResourceUtilTest : public UnitTestBase {
|
||||
protected:
|
||||
BatAdsEpsilonGreedyBanditResourceUtilTest() = default;
|
||||
|
||||
~BatAdsEpsilonGreedyBanditResourceUtilTest() override = default;
|
||||
};
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditResourceUtilTest, SetEligibleSegments) {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
SetEpsilonGreedyBanditEligibleSegments(kSegments);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(kSegments, GetEpsilonGreedyBanditEligibleSegments());
|
||||
}
|
||||
|
||||
TEST_F(BatAdsEpsilonGreedyBanditResourceUtilTest, SetNoEligibleSegments) {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
SetEpsilonGreedyBanditEligibleSegments({});
|
||||
|
||||
// Assert
|
||||
const SegmentList segments = GetEpsilonGreedyBanditEligibleSegments();
|
||||
EXPECT_TRUE(segments.empty());
|
||||
}
|
||||
|
||||
} // namespace resource
|
||||
} // namespace ads
|
||||
@@ -1,44 +0,0 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/segments/segment_json_reader.h"
|
||||
|
||||
#include "base/json/json_reader.h"
|
||||
#include "base/values.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
namespace ads {
|
||||
namespace JSONReader {
|
||||
|
||||
SegmentList ReadSegments(const std::string& json) {
|
||||
absl::optional<base::Value> value = base::JSONReader::Read(json);
|
||||
if (!value) {
|
||||
return {};
|
||||
}
|
||||
|
||||
base::ListValue* list = nullptr;
|
||||
if (!value->GetAsList(&list)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SegmentList segments;
|
||||
for (const auto& element : list->GetList()) {
|
||||
if (!element.is_string()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::string segment = element.GetString();
|
||||
if (segment.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
segments.push_back(segment);
|
||||
}
|
||||
|
||||
return segments;
|
||||
}
|
||||
|
||||
} // namespace JSONReader
|
||||
} // namespace ads
|
||||
@@ -1,21 +0,0 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_JSON_READER_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_JSON_READER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "bat/ads/internal/segments/segment_alias.h"
|
||||
|
||||
namespace ads {
|
||||
namespace JSONReader {
|
||||
|
||||
SegmentList ReadSegments(const std::string& json);
|
||||
|
||||
} // namespace JSONReader
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_JSON_READER_H_
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/segments/segment_json_reader.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BatAds*
|
||||
|
||||
namespace ads {
|
||||
namespace JSONReader {
|
||||
|
||||
TEST(BatAdsSegmentsJsonReaderTest, ValidJson) {
|
||||
// Arrange
|
||||
const std::string json =
|
||||
R"(["technology & computing","personal finance-banking","food & drink-restaurants"])";
|
||||
|
||||
// Act
|
||||
const SegmentList segments = ReadSegments(json);
|
||||
|
||||
// Assert
|
||||
const SegmentList expected_segments = {"technology & computing",
|
||||
"personal finance-banking",
|
||||
"food & drink-restaurants"};
|
||||
EXPECT_EQ(expected_segments, segments);
|
||||
}
|
||||
|
||||
TEST(BatAdsSegmentsJsonReaderTest, InvalidJson) {
|
||||
// Arrange
|
||||
const std::string json = R"({FOOBAR})";
|
||||
|
||||
// Act
|
||||
const SegmentList segments = ReadSegments(json);
|
||||
|
||||
// Assert
|
||||
const SegmentList expected_segments = {};
|
||||
EXPECT_EQ(expected_segments, segments);
|
||||
}
|
||||
|
||||
} // namespace JSONReader
|
||||
} // namespace ads
|
||||
@@ -1,30 +0,0 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/segments/segment_json_writer.h"
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/values.h"
|
||||
|
||||
namespace ads {
|
||||
namespace JSONWriter {
|
||||
|
||||
std::string WriteSegments(const SegmentList& segments) {
|
||||
base::Value list(base::Value::Type::LIST);
|
||||
|
||||
for (const auto& segment : segments) {
|
||||
DCHECK(!segment.empty());
|
||||
list.Append(segment);
|
||||
}
|
||||
|
||||
std::string json;
|
||||
base::JSONWriter::Write(list, &json);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
} // namespace JSONWriter
|
||||
} // namespace ads
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/segments/segment_json_writer.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BatAds*
|
||||
|
||||
namespace ads {
|
||||
namespace JSONWriter {
|
||||
|
||||
TEST(BatAdsSegmentsJsonWriterTest, Segments) {
|
||||
// Arrange
|
||||
const SegmentList segments = {"technology & computing",
|
||||
"personal finance-banking",
|
||||
"food & drink-restaurants"};
|
||||
|
||||
// Act
|
||||
const std::string json = WriteSegments(segments);
|
||||
|
||||
// Assert
|
||||
const std::string expected_json =
|
||||
R"(["technology & computing","personal finance-banking","food & drink-restaurants"])";
|
||||
EXPECT_EQ(expected_json, json);
|
||||
}
|
||||
|
||||
TEST(BatAdsSegmentsJsonWriterTest, NoSegments) {
|
||||
// Arrange
|
||||
const SegmentList segments = {};
|
||||
|
||||
// Act
|
||||
const std::string json = WriteSegments(segments);
|
||||
|
||||
// Assert
|
||||
const std::string expected_json = R"([])";
|
||||
EXPECT_EQ(expected_json, json);
|
||||
}
|
||||
|
||||
} // namespace JSONWriter
|
||||
} // namespace ads
|
||||
@@ -32,8 +32,8 @@ SegmentList GetSegments(const T& creative_ads) {
|
||||
}
|
||||
|
||||
std::string GetParentSegment(const std::string& segment);
|
||||
bool MatchParentSegments(const std::string& lhs, const std::string& rhs);
|
||||
|
||||
bool MatchParentSegments(const std::string& lhs, const std::string& rhs);
|
||||
SegmentList GetParentSegments(const SegmentList& segments);
|
||||
|
||||
bool HasChildSegment(const std::string& segment);
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
#include "bat/ads/internal/segments/segment_util.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "bat/ads/internal/base/unittest/unittest_base.h"
|
||||
#include "bat/ads/internal/base/unittest/unittest_file_util.h"
|
||||
#include "bat/ads/internal/catalog/catalog_info.h"
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/segments/segment_values_util.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/check.h"
|
||||
|
||||
namespace ads {
|
||||
|
||||
base::Value::List SegmentsToValue(const SegmentList& segments) {
|
||||
base::Value::List list;
|
||||
|
||||
for (const auto& segment : segments) {
|
||||
DCHECK(!segment.empty());
|
||||
list.Append(segment);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
SegmentList SegmentsFromValue(const base::Value::List& value) {
|
||||
SegmentList segments;
|
||||
|
||||
for (const auto& item : value) {
|
||||
if (!item.is_string()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::string& segment = item.GetString();
|
||||
if (segment.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
segments.push_back(segment);
|
||||
}
|
||||
|
||||
return segments;
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
+7
-9
@@ -1,21 +1,19 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_JSON_WRITER_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_JSON_WRITER_H_
|
||||
|
||||
#include <string>
|
||||
#ifndef BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_VALUES_UTIL_H_
|
||||
#define BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_VALUES_UTIL_H_
|
||||
|
||||
#include "base/values.h"
|
||||
#include "bat/ads/internal/segments/segment_alias.h"
|
||||
|
||||
namespace ads {
|
||||
namespace JSONWriter {
|
||||
|
||||
std::string WriteSegments(const SegmentList& segments);
|
||||
base::Value::List SegmentsToValue(const SegmentList& segments);
|
||||
SegmentList SegmentsFromValue(const base::Value::List& value);
|
||||
|
||||
} // namespace JSONWriter
|
||||
} // namespace ads
|
||||
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_JSON_WRITER_H_
|
||||
#endif // BRAVE_VENDOR_BAT_NATIVE_ADS_SRC_BAT_ADS_INTERNAL_SEGMENTS_SEGMENT_VALUES_UTIL_H_
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "bat/ads/internal/segments/segment_values_util.h"
|
||||
|
||||
#include "base/test/values_test_util.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
// npm run test -- brave_unit_tests --filter=BatAds*
|
||||
|
||||
namespace ads {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kSegmentsAsJson[] =
|
||||
R"(["technology & computing","personal finance-banking","food & drink-restaurants"])";
|
||||
constexpr char kNoSegmentsAsJson[] = "[]";
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(BatAdsSegmentValuesUtilTest, SegmentsToValue) {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
const base::Value::List list =
|
||||
SegmentsToValue({"technology & computing", "personal finance-banking",
|
||||
"food & drink-restaurants"});
|
||||
|
||||
// Assert
|
||||
const base::Value value = base::test::ParseJson(kSegmentsAsJson);
|
||||
const base::Value::List* expected_list = value.GetIfList();
|
||||
ASSERT_TRUE(expected_list);
|
||||
|
||||
EXPECT_EQ(*expected_list, list);
|
||||
}
|
||||
|
||||
TEST(BatAdsSegmentValuesUtilTest, NoSegmentsToValue) {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
const base::Value::List list = SegmentsToValue({});
|
||||
|
||||
// Assert
|
||||
const base::Value value = base::test::ParseJson(kNoSegmentsAsJson);
|
||||
const base::Value::List* expected_list = value.GetIfList();
|
||||
ASSERT_TRUE(expected_list);
|
||||
|
||||
EXPECT_EQ(*expected_list, list);
|
||||
}
|
||||
|
||||
TEST(BatAdsSegmentValuesUtilTest, SegmentsFromValue) {
|
||||
// Arrange
|
||||
const base::Value value = base::test::ParseJson(kSegmentsAsJson);
|
||||
const base::Value::List* list = value.GetIfList();
|
||||
ASSERT_TRUE(list);
|
||||
|
||||
// Act
|
||||
const SegmentList segments = SegmentsFromValue(*list);
|
||||
|
||||
// Assert
|
||||
const SegmentList expected_segments = {"technology & computing",
|
||||
"personal finance-banking",
|
||||
"food & drink-restaurants"};
|
||||
EXPECT_EQ(expected_segments, segments);
|
||||
}
|
||||
|
||||
TEST(BatAdsSegmentValuesUtilTest, NoSegmentsFromValue) {
|
||||
// Arrange
|
||||
const base::Value value = base::test::ParseJson(kNoSegmentsAsJson);
|
||||
const base::Value::List* list = value.GetIfList();
|
||||
ASSERT_TRUE(list);
|
||||
|
||||
// Act
|
||||
const SegmentList segments = SegmentsFromValue(*list);
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(segments.empty());
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
+3
-5
@@ -49,13 +49,11 @@ const char kCatalogLastUpdated[] = "brave.brave_ads.catalog_last_updated";
|
||||
const char kIssuerPing[] = "brave.brave_ads.issuer_ping";
|
||||
const char kIssuers[] = "brave.brave_ads.issuers";
|
||||
|
||||
// Stores epsilon greedy bandit arms
|
||||
// Stores epsilon greedy bandit
|
||||
const char kEpsilonGreedyBanditArms[] =
|
||||
"brave.brave_ads.epsilon_greedy_bandit_arms";
|
||||
|
||||
// Stores epsilon greedy bandit eligible segments
|
||||
"brave.brave_ads.epsilon_greedy_bandit_arms.v2";
|
||||
const char kEpsilonGreedyBanditEligibleSegments[] =
|
||||
"brave.brave_ads.epsilon_greedy_bandit_eligible_segments";
|
||||
"brave.brave_ads.epsilon_greedy_bandit_eligible_segments.v2";
|
||||
|
||||
// Ads
|
||||
const char kServeAdAt[] = "brave.brave_ads.serve_ad_at";
|
||||
|
||||
Reference in New Issue
Block a user