barcode_detection_provider_mac_unittest.mm 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/shape_detection/barcode_detection_provider_mac.h"
  5. #import <Vision/Vision.h>
  6. #include <memory>
  7. #include <string>
  8. #include "base/bind.h"
  9. #include "base/run_loop.h"
  10. #include "base/test/bind.h"
  11. #include "base/test/gmock_callback_support.h"
  12. #include "base/test/task_environment.h"
  13. #include "mojo/public/cpp/bindings/remote.h"
  14. #include "mojo/public/cpp/bindings/self_owned_receiver.h"
  15. #include "mojo/public/cpp/test_support/test_utils.h"
  16. #include "services/shape_detection/barcode_detection_impl_mac_vision.h"
  17. #include "services/shape_detection/barcode_detection_provider_mac.h"
  18. #include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h"
  19. #include "testing/gmock/include/gmock/gmock.h"
  20. #include "testing/gtest/include/gtest/gtest.h"
  21. using base::test::RunClosure;
  22. using ::testing::NiceMock;
  23. using ::testing::Return;
  24. using ::testing::TestWithParam;
  25. using ::testing::ValuesIn;
  26. namespace shape_detection {
  27. namespace {
  28. static const std::vector<mojom::BarcodeFormat>& CISupportedFormats = {
  29. mojom::BarcodeFormat::QR_CODE};
  30. static const std::vector<mojom::BarcodeFormat>& VisionSupportedFormats = {
  31. mojom::BarcodeFormat::AZTEC, mojom::BarcodeFormat::CODE_128,
  32. mojom::BarcodeFormat::CODE_39, mojom::BarcodeFormat::CODE_93,
  33. mojom::BarcodeFormat::DATA_MATRIX, mojom::BarcodeFormat::EAN_13,
  34. mojom::BarcodeFormat::EAN_8, mojom::BarcodeFormat::ITF,
  35. mojom::BarcodeFormat::PDF417, mojom::BarcodeFormat::QR_CODE,
  36. mojom::BarcodeFormat::UPC_E};
  37. static const std::vector<mojom::BarcodeFormat>& MockVisionSupportedFormats = {
  38. mojom::BarcodeFormat::AZTEC, mojom::BarcodeFormat::DATA_MATRIX,
  39. mojom::BarcodeFormat::QR_CODE};
  40. static NSArray<VNBarcodeSymbology>* MockVisionSupportedSymbologyStrings = @[
  41. VNBarcodeSymbologyAztec, VNBarcodeSymbologyDataMatrix, VNBarcodeSymbologyQR
  42. ];
  43. class MockVisionAPI : public VisionAPIInterface {
  44. public:
  45. MOCK_CONST_METHOD0(GetSupportedSymbologies,
  46. NSArray<VNBarcodeSymbology>*(void));
  47. };
  48. std::unique_ptr<mojom::BarcodeDetectionProvider> CreateBarcodeProviderMac(
  49. std::unique_ptr<VisionAPIInterface> vision_api) {
  50. return std::make_unique<BarcodeDetectionProviderMac>(std::move(vision_api));
  51. }
  52. std::unique_ptr<VisionAPIInterface> CreateNullVisionAPI() {
  53. return nullptr;
  54. }
  55. std::unique_ptr<VisionAPIInterface> CreateVisionAPI() {
  56. return VisionAPIInterface::Create();
  57. }
  58. std::unique_ptr<VisionAPIInterface> CreateMockVisionAPI(
  59. NSArray<VNBarcodeSymbology>* returned_symbologies) {
  60. std::unique_ptr<NiceMock<MockVisionAPI>> mock_vision_api =
  61. std::make_unique<NiceMock<MockVisionAPI>>();
  62. ON_CALL(*mock_vision_api, GetSupportedSymbologies())
  63. .WillByDefault(Return(returned_symbologies));
  64. return mock_vision_api;
  65. }
  66. using VisionAPIInterfaceFactory =
  67. base::RepeatingCallback<std::unique_ptr<VisionAPIInterface>()>;
  68. struct TestParams {
  69. const std::vector<mojom::BarcodeFormat> formats;
  70. bool test_vision_api;
  71. VisionAPIInterfaceFactory vision_api;
  72. } kTestParams[] = {
  73. {CISupportedFormats, false, base::BindRepeating(&CreateNullVisionAPI)},
  74. {VisionSupportedFormats, true, base::BindRepeating(&CreateVisionAPI)},
  75. {MockVisionSupportedFormats, true,
  76. base::BindRepeating(&CreateMockVisionAPI,
  77. MockVisionSupportedSymbologyStrings)},
  78. };
  79. }
  80. class BarcodeDetectionProviderMacTest
  81. : public TestWithParam<struct TestParams> {
  82. public:
  83. ~BarcodeDetectionProviderMacTest() override = default;
  84. void SetUp() override {
  85. ASSERT_EQ([MockVisionSupportedSymbologyStrings count],
  86. MockVisionSupportedFormats.size());
  87. }
  88. void EnumerateSupportedFormatsCallback(
  89. const std::vector<mojom::BarcodeFormat>& expected,
  90. const std::vector<mojom::BarcodeFormat>& results) {
  91. EXPECT_THAT(results,
  92. testing::ElementsAreArray(expected.begin(), expected.end()));
  93. OnEnumerateSupportedFormats();
  94. }
  95. MOCK_METHOD0(OnEnumerateSupportedFormats, void(void));
  96. std::unique_ptr<mojom::BarcodeDetectionProvider> provider_;
  97. base::test::SingleThreadTaskEnvironment task_environment_;
  98. };
  99. TEST_P(BarcodeDetectionProviderMacTest, EnumerateSupportedBarcodes) {
  100. if (!GetParam().test_vision_api) {
  101. LOG(WARNING) << "Barcode Detection for this (library, OS version) pair is "
  102. "not supported, skipping test.";
  103. return;
  104. }
  105. provider_ = CreateBarcodeProviderMac(GetParam().vision_api.Run());
  106. base::RunLoop run_loop;
  107. base::RepeatingClosure quit_closure = run_loop.QuitClosure();
  108. EXPECT_CALL(*this, OnEnumerateSupportedFormats())
  109. .WillOnce(RunClosure(quit_closure));
  110. provider_->EnumerateSupportedFormats(base::BindOnce(
  111. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  112. base::Unretained(this), GetParam().formats));
  113. run_loop.Run();
  114. }
  115. INSTANTIATE_TEST_SUITE_P(,
  116. BarcodeDetectionProviderMacTest,
  117. ValuesIn(kTestParams));
  118. TEST_F(BarcodeDetectionProviderMacTest, EnumerateSupportedBarcodesCached) {
  119. auto mock_vision_api = std::make_unique<MockVisionAPI>();
  120. ON_CALL(*mock_vision_api, GetSupportedSymbologies())
  121. .WillByDefault(Return(MockVisionSupportedSymbologyStrings));
  122. EXPECT_CALL(*mock_vision_api, GetSupportedSymbologies());
  123. provider_ = CreateBarcodeProviderMac(std::move(mock_vision_api));
  124. provider_->EnumerateSupportedFormats(base::BindOnce(
  125. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  126. base::Unretained(this), MockVisionSupportedFormats));
  127. provider_->EnumerateSupportedFormats(base::BindOnce(
  128. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  129. base::Unretained(this), MockVisionSupportedFormats));
  130. provider_->EnumerateSupportedFormats(base::BindOnce(
  131. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  132. base::Unretained(this), MockVisionSupportedFormats));
  133. }
  134. TEST_F(BarcodeDetectionProviderMacTest, EnumerateSupportedBarcodesUnknown) {
  135. NSMutableArray* mock_supported_symbologies =
  136. [NSMutableArray arrayWithArray:MockVisionSupportedSymbologyStrings];
  137. [mock_supported_symbologies addObject:@"FooSymbology"];
  138. std::unique_ptr<VisionAPIInterface> mock_vision_api =
  139. CreateMockVisionAPI(mock_supported_symbologies);
  140. provider_ = CreateBarcodeProviderMac(std::move(mock_vision_api));
  141. provider_->EnumerateSupportedFormats(base::BindOnce(
  142. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  143. base::Unretained(this), MockVisionSupportedFormats));
  144. }
  145. TEST_F(BarcodeDetectionProviderMacTest, EnumerateSupportedBarcodesErrored) {
  146. std::unique_ptr<VisionAPIInterface> mock_vision_api =
  147. CreateMockVisionAPI(@[]);
  148. provider_ = CreateBarcodeProviderMac(std::move(mock_vision_api));
  149. provider_->EnumerateSupportedFormats(base::BindOnce(
  150. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  151. base::Unretained(this), std::vector<mojom::BarcodeFormat>()));
  152. provider_->EnumerateSupportedFormats(base::BindOnce(
  153. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  154. base::Unretained(this), std::vector<mojom::BarcodeFormat>()));
  155. provider_->EnumerateSupportedFormats(base::BindOnce(
  156. &BarcodeDetectionProviderMacTest::EnumerateSupportedFormatsCallback,
  157. base::Unretained(this), std::vector<mojom::BarcodeFormat>()));
  158. }
  159. TEST_F(BarcodeDetectionProviderMacTest, HintFormats) {
  160. mojo::Remote<mojom::BarcodeDetectionProvider> provider_remote;
  161. mojo::MakeSelfOwnedReceiver(CreateBarcodeProviderMac(CreateVisionAPI()),
  162. provider_remote.BindNewPipeAndPassReceiver());
  163. auto options = mojom::BarcodeDetectorOptions::New();
  164. options->formats = {mojom::BarcodeFormat::UNKNOWN};
  165. mojo::test::BadMessageObserver observer;
  166. mojo::Remote<mojom::BarcodeDetection> impl;
  167. provider_remote->CreateBarcodeDetection(impl.BindNewPipeAndPassReceiver(),
  168. std::move(options));
  169. EXPECT_EQ("Formats hint contains UNKNOWN BarcodeFormat.",
  170. observer.WaitForBadMessage());
  171. }
  172. } // shape_detection namespace