1// Copyright 2013 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 5#include "base/message_loop/message_loop.h" 6#include "chrome/browser/local_discovery/privet_local_printer_lister.h" 7#include "chrome/browser/local_discovery/test_service_discovery_client.h" 8#include "net/url_request/test_url_fetcher_factory.h" 9#include "net/url_request/url_request_test_util.h" 10 11#include "testing/gmock/include/gmock/gmock.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14using testing::StrictMock; 15using testing::_; 16 17namespace local_discovery { 18 19namespace { 20 21const uint8 kAnnouncePacket[] = { 22 // Header 23 0x00, 0x00, // ID is zeroed out 24 0x80, 0x00, // Standard query response, no error 25 0x00, 0x00, // No questions (for simplicity) 26 0x00, 0x05, // 5 RR (answers) 27 0x00, 0x00, // 0 authority RRs 28 0x00, 0x00, // 0 additional RRs 29 30 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r', 31 0x04, '_', 's', 'u', 'b', 32 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 33 0x04, '_', 't', 'c', 'p', 34 0x05, 'l', 'o', 'c', 'a', 'l', 35 0x00, 36 0x00, 0x0c, // TYPE is PTR. 37 0x00, 0x01, // CLASS is IN. 38 0x00, 0x00, // TTL (4 bytes) is 32768 second. 39 0x10, 0x00, 40 0x00, 0x0c, // RDLENGTH is 12 bytes. 41 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 42 0xc0, 0x0c, 43 44 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 45 0xc0, 0x0c, 46 0x00, 0x10, // TYPE is TXT. 47 0x00, 0x01, // CLASS is IN. 48 0x00, 0x00, // TTL (4 bytes) is 32768 seconds. 49 0x01, 0x00, 50 0x00, 0x37, // RDLENGTH is 55 bytes. 51 0x06, 'i', 'd', '=', 'r', 'e', 'g', 52 0x10, 't', 'y', '=', 'S', 'a', 'm', 'p', 'l', 'e', ' ', 53 'd', 'e', 'v', 'i', 'c', 'e', 54 0x1e, 'n', 'o', 't', 'e', '=', 55 'S', 'a', 'm', 'p', 'l', 'e', ' ', 'd', 'e', 'v', 'i', 'c', 'e', ' ', 56 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 57 58 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 59 0xc0, 0x0c, 60 0x00, 0x21, // Type is SRV 61 0x00, 0x01, // CLASS is IN 62 0x00, 0x00, // TTL (4 bytes) is 32768 second. 63 0x10, 0x00, 64 0x00, 0x17, // RDLENGTH is 23 65 0x00, 0x00, 66 0x00, 0x00, 67 0x22, 0xb8, // port 8888 68 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 69 0x05, 'l', 'o', 'c', 'a', 'l', 70 0x00, 71 72 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 73 0x05, 'l', 'o', 'c', 'a', 'l', 74 0x00, 75 0x00, 0x01, // Type is A 76 0x00, 0x01, // CLASS is IN 77 0x00, 0x00, // TTL (4 bytes) is 32768 second. 78 0x10, 0x00, 79 0x00, 0x04, // RDLENGTH is 4 80 0x01, 0x02, 0x03, 0x04, // 1.2.3.4 81 82 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 83 0x05, 'l', 'o', 'c', 'a', 'l', 84 0x00, 85 0x00, 0x1C, // Type is AAAA 86 0x00, 0x01, // CLASS is IN 87 0x00, 0x00, // TTL (4 bytes) is 32768 second. 88 0x10, 0x00, 89 0x00, 0x10, // RDLENGTH is 16 90 0x01, 0x02, 0x03, 0x04, // 1.2.3.4 91 0x01, 0x02, 0x03, 0x04, 92 0x01, 0x02, 0x03, 0x04, 93 0x01, 0x02, 0x03, 0x04, 94}; 95 96const char kInfoIsLocalPrinter[] = "{" 97 "\"api\" : [ \"/privet/printer/submitdoc\" ]," 98 "\"x-privet-token\" : \"sample\"" 99 "}"; 100 101const char kInfoIsNotLocalPrinter[] = "{" 102 "\"api\" : [ \"/privet/register\" ]," 103 "\"x-privet-token\" : \"sample\"" 104 "}"; 105 106const char kServiceName[] = "myService._printer._sub._privet._tcp.local"; 107 108const char kPrivetInfoURL[] = "http://1.2.3.4:8888/privet/info"; 109 110class MockLocalPrinterListerDelegate 111 : public PrivetLocalPrinterLister::Delegate { 112 public: 113 MockLocalPrinterListerDelegate() { 114 } 115 116 virtual ~MockLocalPrinterListerDelegate() { 117 } 118 119 MOCK_METHOD4(LocalPrinterChanged, void(bool added, 120 const std::string& name, 121 bool has_local_printing, 122 const DeviceDescription& description)); 123 124 MOCK_METHOD1(LocalPrinterRemoved, void(const std::string& name)); 125 126 MOCK_METHOD0(LocalPrinterCacheFlushed, void()); 127}; 128 129class PrivetLocalPrinterListerTest : public testing::Test { 130 public: 131 PrivetLocalPrinterListerTest() { 132 test_service_discovery_client_ = new TestServiceDiscoveryClient(); 133 test_service_discovery_client_->Start(); 134 url_request_context_ = new net::TestURLRequestContextGetter( 135 base::MessageLoopProxy::current()); 136 local_printer_lister_.reset(new PrivetLocalPrinterLister( 137 test_service_discovery_client_.get(), 138 url_request_context_.get(), 139 &delegate_)); 140 } 141 142 ~PrivetLocalPrinterListerTest() { 143 } 144 145 bool SuccessfulResponseToURL(const GURL& url, 146 const std::string& response) { 147 net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0); 148 EXPECT_TRUE(fetcher); 149 EXPECT_EQ(url, fetcher->GetOriginalURL()); 150 151 if (!fetcher || url != fetcher->GetOriginalURL()) 152 return false; 153 154 fetcher->SetResponseString(response); 155 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 156 net::OK)); 157 fetcher->set_response_code(200); 158 fetcher->delegate()->OnURLFetchComplete(fetcher); 159 return true; 160 } 161 162 void SimulateReceive(const uint8* packet, size_t size) { 163 test_service_discovery_client_->SimulateReceive(packet, size); 164 message_loop_.RunUntilIdle(); 165 } 166 167 void ExpectAnyPacket() { 168 EXPECT_CALL(*test_service_discovery_client_, OnSendTo(_)) 169 .Times(2); 170 } 171 172 protected: 173 base::MessageLoop message_loop_; 174 scoped_refptr<TestServiceDiscoveryClient> test_service_discovery_client_; 175 scoped_refptr<net::TestURLRequestContextGetter> url_request_context_; 176 scoped_ptr<PrivetLocalPrinterLister> local_printer_lister_; 177 net::TestURLFetcherFactory fetcher_factory_; 178 StrictMock<MockLocalPrinterListerDelegate> delegate_; 179}; 180 181TEST_F(PrivetLocalPrinterListerTest, PrinterAddedTest) { 182 ExpectAnyPacket(); 183 184 local_printer_lister_->Start(); 185 186 SimulateReceive(kAnnouncePacket, sizeof(kAnnouncePacket)); 187 188 EXPECT_CALL(delegate_, LocalPrinterChanged(true, kServiceName, true, _)); 189 190 EXPECT_TRUE(SuccessfulResponseToURL( 191 GURL(kPrivetInfoURL), 192 std::string(kInfoIsLocalPrinter))); 193}; 194 195TEST_F(PrivetLocalPrinterListerTest, NonPrinterAddedTest) { 196 ExpectAnyPacket(); 197 198 local_printer_lister_->Start(); 199 200 SimulateReceive(kAnnouncePacket, sizeof(kAnnouncePacket)); 201 202 EXPECT_CALL(delegate_, LocalPrinterChanged(true, kServiceName, false, _)); 203 204 EXPECT_TRUE(SuccessfulResponseToURL( 205 GURL(kPrivetInfoURL), 206 std::string(kInfoIsNotLocalPrinter))); 207}; 208 209} // namespace 210 211} // namespace local_discovery 212