tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DesktopLauncherDownloaderTest.cpp (4136B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 #include "gtest/gtest.h"
      5 #include <windows.h>
      6 #include <string>
      7 #include <shellapi.h>
      8 #include <winhttp.h>
      9 
     10 #include "find_firefox.h"
     11 #include "tempfile_name.h"
     12 #include "download_firefox.h"
     13 #include "data_sink.h"
     14 
     15 static const size_t python_path_len = 32768;
     16 static wchar_t python_path[python_path_len];
     17 
     18 static wchar_t* getPythonPath() {
     19  DWORD res = GetEnvironmentVariableW(L"PYTHON", python_path, python_path_len);
     20  if (res == 0) {
     21    std::wcout << L"Can't find python" << std::endl;
     22    return nullptr;
     23  }
     24  return python_path;
     25 }
     26 
     27 static HANDLE startWebServer() {
     28  SHELLEXECUTEINFOW execInfo{};
     29  execInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
     30  execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC;
     31  execInfo.lpVerb = L"open";
     32  execInfo.lpFile = getPythonPath();
     33  if (!execInfo.lpFile) {
     34    // Can't find Python
     35    return nullptr;
     36  }
     37  execInfo.lpParameters =
     38      L"-m http.server --protocol HTTP/1.1 --bind 127.0.0.1 9191";
     39  execInfo.nShow = SW_HIDE;
     40 
     41  if (!ShellExecuteExW(&execInfo)) {
     42    std::wcout << L"Can't exec python web server" << std::endl;
     43    return nullptr;
     44  }
     45  return execInfo.hProcess;
     46 }
     47 
     48 static void stopWebServer(HANDLE processHandle) {
     49  if (processHandle) {
     50    TerminateProcess(processHandle, 0);
     51    CloseHandle(processHandle);
     52  }
     53  processHandle = nullptr;
     54 }
     55 
     56 class StringDataSink : public DataSink {
     57 public:
     58  std::string data;
     59 
     60  bool accept(char* buf, int count) {
     61    std::string str(buf, count);
     62    data += str;
     63    return true;
     64  }
     65 };
     66 
     67 static void DownloadAndCheckStub(const std::wstring& product) {
     68  StringDataSink sink;
     69  std::wstring object_name = L"/?os=win64&lang=en-US&product=" + product;
     70 
     71  ErrCode ec =
     72      download_file(&sink, L"download.mozilla.org", INTERNET_DEFAULT_HTTPS_PORT,
     73                    true,  // HTTPS
     74                    object_name, L"application/x-msdos-program");
     75 
     76  // First, ensure that the request was successful
     77  ASSERT_EQ(ec, ErrCode::OK);
     78 
     79  // All .exe files start with MZ
     80  ASSERT_EQ((unsigned char)sink.data[0], 'M')
     81      << "File is not a valid PE executable";
     82  ASSERT_EQ((unsigned char)sink.data[1], 'Z');
     83 }
     84 
     85 class DesktopLauncherDownloaderTest : public ::testing::Test {
     86 protected:
     87  HANDLE serverProcessHandle = nullptr;
     88 
     89  void SetUp() override { serverProcessHandle = startWebServer(); }
     90 
     91  void TearDown() override { stopWebServer(serverProcessHandle); }
     92 };
     93 
     94 TEST_F(DesktopLauncherDownloaderTest, TestDownloadFileSuccess) {
     95  if (serverProcessHandle == nullptr) {
     96    FAIL() << "No process.";
     97  }
     98  StringDataSink sink;
     99  ErrCode ec =
    100      download_file(&sink, L"localhost", 9191, false,
    101                    L"/desktop_launcher_test_content.txt", L"text/plain");
    102  ASSERT_EQ(ec, ErrCode::OK);
    103  ASSERT_STREQ(sink.data.c_str(), "Testing 123");
    104 }
    105 
    106 TEST_F(DesktopLauncherDownloaderTest, TestDownloadFile_NotFound) {
    107  if (serverProcessHandle == nullptr) {
    108    FAIL() << "No process.";
    109  }
    110  StringDataSink sink;
    111  ErrCode ec = download_file(&sink, L"localhost", 9191, false,
    112                             L"/this_file_should_not_exist.txt", L"text/plain");
    113  ASSERT_EQ(ec, ErrCode::ERR_FILE_NOT_FOUND);
    114  ASSERT_STREQ(sink.data.c_str(), "");
    115 }
    116 
    117 TEST_F(DesktopLauncherDownloaderTest, TestDownloadFile_InvalidRequest) {
    118  if (serverProcessHandle == nullptr) {
    119    FAIL() << "No process.";
    120  }
    121  StringDataSink sink;
    122  // Requesting https download from the non-https server.
    123  ErrCode ec = download_file(&sink, L"localhost", 9191, true,
    124                             L"/name_doesnt_matter.txt", L"text/plain");
    125  ASSERT_EQ(ec, ErrCode::ERR_REQUEST_INVALID);
    126  ASSERT_STREQ(sink.data.c_str(), "");
    127 }
    128 
    129 TEST(DesktopLauncherDownloaderReal, DownloadNightlyStub)
    130 {
    131  DownloadAndCheckStub(L"firefox-nightly-stub");
    132 }
    133 
    134 TEST(DesktopLauncherDownloaderReal, DownloadBetaStub)
    135 {
    136  DownloadAndCheckStub(L"firefox-beta-stub");
    137 }
    138 
    139 TEST(DesktopLauncherDownloaderReal, DownloadDevStub)
    140 {
    141  DownloadAndCheckStub(L"firefox-devedition-stub");
    142 }