Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  TestGetFilesHelper.cpp

  Sprache: C
 

/* 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 <thread>

#include "SpecialSystemDirectory.h"
#include "gtest/gtest.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/dom/BlobImpl.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/GetFilesHelper.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/gtest/MozAssertions.h"
#include "mozilla/media/MediaUtils.h"
#include "nsIFile.h"

using namespace mozilla;
using namespace mozilla::dom;

nsCOMPtr<nsIFile> MakeFileFromPathSegments(
    const nsTArray<const char*>& aPathSegments) {
  nsCOMPtr<nsIFile> file;
  MOZ_ALWAYS_SUCCEEDS(GetSpecialSystemDirectory(OS_CurrentWorkingDirectory,
                                                getter_AddRefs(file)));
  for (const auto* pathSegment : aPathSegments) {
    MOZ_ALWAYS_SUCCEEDS(
        file->AppendRelativePath(NS_ConvertASCIItoUTF16(pathSegment)));
  }
  return file;
}

nsresult AppendFileOrDirectory(nsTArray<OwningFileOrDirectory>& aDirectories,
                               const nsTArray<const char*>& aPathSegments) {
  bool exists = false;
  int retryCount = 5;
  nsCOMPtr<nsIFile> file = MakeFileFromPathSegments(aPathSegments);
  while (retryCount--) {
    if (NS_SUCCEEDED(file->Exists(&exists))) {
      break;
    }
    // May require retrying (bug 1963029)
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }
  NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
  bool isDir;
  MOZ_ALWAYS_SUCCEEDS(file->IsDirectory(&isDir));
  if (isDir) {
    // We just need to iterate over the directory, so use the junk scope
    RefPtr<Directory> directory =
        Directory::Create(xpc::NativeGlobal(xpc::PrivilegedJunkScope()), file);
    NS_ENSURE_TRUE(directory, NS_ERROR_FAILURE);

    OwningFileOrDirectory* owningDirectory = aDirectories.EmplaceBack();
    owningDirectory->SetAsDirectory() = directory;
  } else {
    OwningFileOrDirectory* owningDirectory = aDirectories.EmplaceBack();
    RefPtr<File> fileObject = File::CreateFromFile(
        xpc::NativeGlobal(xpc::PrivilegedJunkScope()), file);
    owningDirectory->SetAsFile() = fileObject;
  }
  return NS_OK;
}

struct BoolStruct {
  bool mValue = false;
};

class FilesCallback : public GetFilesCallback {
 public:
  FilesCallback(std::atomic<bool>& aGotResponse,
                const nsTArray<nsString>& aExpectedPaths)
      : mGotResponse(aGotResponse), mExpectedPaths(aExpectedPaths.Clone()) {}

  // -------------------
  // GetFilesCallback
  // -------------------
  void Callback(nsresult aStatus,
                const FallibleTArray<RefPtr<BlobImpl>>& aBlobImpls) override {
    EXPECT_EQ(aBlobImpls.Length(), mExpectedPaths.Length());
    for (const auto& blob : aBlobImpls) {
      nsString path;
      ErrorResult error;
      blob->GetMozFullPathInternal(path, error);
      ASSERT_EQ(error.StealNSResult(), NS_OK);
      ASSERT_TRUE(mExpectedPaths.Contains(path));
    }
    mGotResponse = true;
  }

 private:
  std::atomic<bool>& mGotResponse;
  nsTArray<nsString> mExpectedPaths;
};

nsTArray<nsString> GetExpectedPaths(
    const nsTArray<nsTArray<const char*>>& aPathSegmentsArray) {
  nsTArray<nsString> expectedPaths(aPathSegmentsArray.Length());
  for (const auto& pathSegments : aPathSegmentsArray) {
    auto file = MakeFileFromPathSegments(pathSegments);
    nsString expectedPath;
    MOZ_ALWAYS_SUCCEEDS(file->GetPath(expectedPath));
    expectedPaths.AppendElement(expectedPath);
  }
  return expectedPaths;
}

void ExpectGetFilesHelperResponse(
    RefPtr<GetFilesHelper> aHelper,
    const nsTArray<nsTArray<const char*>>& aPathSegmentsArray) {
  nsTArray<nsString> expectedPaths = GetExpectedPaths(aPathSegmentsArray);

  std::atomic<bool> gotCallbackResponse = false;
  std::atomic<bool> gotMozPromiseResponse = false;
  RefPtr<FilesCallback> callback =
      MakeRefPtr<FilesCallback>(gotCallbackResponse, expectedPaths);
  aHelper->AddCallback(callback);
  auto mozPromise = MakeRefPtr<GetFilesHelper::MozPromiseType>(__func__);
  aHelper->AddMozPromise(mozPromise,
                         xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
  mozPromise->Then(
      GetMainThreadSerialEventTarget(), __func__,
      [&gotMozPromiseResponse,
       &expectedPaths](const nsTArray<RefPtr<mozilla::dom::File>>& aFiles) {
        EXPECT_EQ(aFiles.Length(), expectedPaths.Length());
        for (const auto& file : aFiles) {
          nsString path;
          ErrorResult error;
          file->GetMozFullPathInternal(path, error);
          ASSERT_EQ(error.StealNSResult(), NS_OK);
          ASSERT_TRUE(expectedPaths.Contains(path));
        }
        gotMozPromiseResponse = true;
      },
      []() { FAIL() << "MozPromise got rejected!"; });
  // Make timedOut a RefPtr so if we get a response after this function
  // has finished we can safely check that (and don't start accessing stack
  // values that don't exist anymore)
  RefPtr timedOut = MakeRefPtr<media::Refcountable<BoolStruct>>();

  RefPtr<CancelableRunnable> timer =
      NS_NewCancelableRunnableFunction("GetFilesHelper timeout", [&] {
        if (!gotCallbackResponse.load() || !gotMozPromiseResponse.load()) {
          timedOut->mValue = true;
        }
      });
  constexpr uint32_t kTimeout = 10000;
  NS_DelayedDispatchToCurrentThread(do_AddRef(timer), kTimeout);
  mozilla::SpinEventLoopUntil(
      "Waiting for GetFilesHelper result"_ns, [&, timedOut]() {
        return (gotCallbackResponse.load() && gotMozPromiseResponse.load()) ||
               timedOut->mValue;
      });
  timer->Cancel();
  EXPECT_TRUE(gotCallbackResponse);
  EXPECT_TRUE(gotMozPromiseResponse);
  EXPECT_FALSE(timedOut->mValue);
}

TEST(GetFilesHelper, TestSingleDirectory)
{
  nsTArray<OwningFileOrDirectory> directories;
  ASSERT_NS_SUCCEEDED(
      AppendFileOrDirectory(directories, {"getfiles""inner2"}));

  ErrorResult error;
  RefPtr<GetFilesHelper> helper =
      GetFilesHelper::Create(directories, true, error);
  ASSERT_EQ(error.StealNSResult(), NS_OK);

  nsTArray<nsTArray<const char*>> pathSegmentsArray;
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner2""fileinner2.txt"});
  ExpectGetFilesHelperResponse(helper, pathSegmentsArray);
}

TEST(GetFilesHelper, TestSingleNestedDirectory)
{
  nsTArray<OwningFileOrDirectory> directories;
  ASSERT_NS_SUCCEEDED(
      AppendFileOrDirectory(directories, {"getfiles""inner1"}));

  ErrorResult error;
  RefPtr<GetFilesHelper> helper =
      GetFilesHelper::Create(directories, true, error);
  ASSERT_EQ(error.StealNSResult(), NS_OK);

  nsTArray<nsTArray<const char*>> pathSegmentsArray;
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""fileinner1.txt"});
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""inner""fileinnerinner1.txt"});
  ExpectGetFilesHelperResponse(helper, pathSegmentsArray);
}

TEST(GetFilesHelper, TestSingleNestedDirectoryNoRecursion)
{
  nsTArray<OwningFileOrDirectory> directories;
  ASSERT_NS_SUCCEEDED(
      AppendFileOrDirectory(directories, {"getfiles""inner1"}));

  ErrorResult error;
  RefPtr<GetFilesHelper> helper =
      GetFilesHelper::Create(directories, false, error);
  ASSERT_EQ(error.StealNSResult(), NS_OK);

  nsTArray<nsTArray<const char*>> pathSegmentsArray;
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""fileinner1.txt"});
  ExpectGetFilesHelperResponse(helper, pathSegmentsArray);
}

TEST(GetFilesHelper, TestSingleDirectoryWithMultipleNestedChildren)
{
  nsTArray<OwningFileOrDirectory> directories;
  ASSERT_NS_SUCCEEDED(AppendFileOrDirectory(directories, {"getfiles"}));

  ErrorResult error;
  RefPtr<GetFilesHelper> helper =
      GetFilesHelper::Create(directories, true, error);
  ASSERT_EQ(error.StealNSResult(), NS_OK);

  nsTArray<nsTArray<const char*>> pathSegmentsArray;
  pathSegmentsArray.AppendElement(nsTArray{"getfiles""file1.txt"});
  pathSegmentsArray.AppendElement(nsTArray{"getfiles""file2.txt"});
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""fileinner1.txt"});
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""inner""fileinnerinner1.txt"});
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner2""fileinner2.txt"});
  ExpectGetFilesHelperResponse(helper, pathSegmentsArray);
}

TEST(GetFilesHelper, TestSingleFile)
{
  nsTArray<OwningFileOrDirectory> directories;
  ASSERT_NS_SUCCEEDED(AppendFileOrDirectory(
      directories, {"getfiles""inner1""fileinner1.txt"}));

  ErrorResult error;
  RefPtr<GetFilesHelper> helper =
      GetFilesHelper::Create(directories, true, error);
  ASSERT_EQ(error.StealNSResult(), NS_OK);

  nsTArray<nsTArray<const char*>> pathSegmentsArray;
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""fileinner1.txt"});
  ExpectGetFilesHelperResponse(helper, pathSegmentsArray);
}

TEST(GetFilesHelper, TestMultipleFiles)
{
  nsTArray<OwningFileOrDirectory> directories;
  ASSERT_NS_SUCCEEDED(AppendFileOrDirectory(
      directories, {"getfiles""inner1""fileinner1.txt"}));
  ASSERT_NS_SUCCEEDED(AppendFileOrDirectory(
      directories, {"getfiles""inner2""fileinner2.txt"}));

  ErrorResult error;
  RefPtr<GetFilesHelper> helper =
      GetFilesHelper::Create(directories, true, error);
  ASSERT_EQ(error.StealNSResult(), NS_OK);

  nsTArray<nsTArray<const char*>> pathSegmentsArray;
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""fileinner1.txt"});
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner2""fileinner2.txt"});
  ExpectGetFilesHelperResponse(helper, pathSegmentsArray);
}

// Content Analysis can use GetFilesHelper with multiple directories,
// so make sure that works.
TEST(GetFilesHelper, TestMultipleDirectories)
{
  nsTArray<OwningFileOrDirectory> directories;
  ASSERT_NS_SUCCEEDED(
      AppendFileOrDirectory(directories, {"getfiles""inner1"}));
  ASSERT_NS_SUCCEEDED(
      AppendFileOrDirectory(directories, {"getfiles""inner2"}));

  ErrorResult error;
  RefPtr<GetFilesHelper> helper =
      GetFilesHelper::Create(directories, true, error);
  ASSERT_EQ(error.StealNSResult(), NS_OK);

  nsTArray<nsTArray<const char*>> pathSegmentsArray;
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""fileinner1.txt"});
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner1""inner""fileinnerinner1.txt"});
  pathSegmentsArray.AppendElement(
      nsTArray{"getfiles""inner2""fileinner2.txt"});
  ExpectGetFilesHelperResponse(helper, pathSegmentsArray);
}

Messung V0.5 in Prozent
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet am  2026-08-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=434850
#Domains=655579