Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  TestEtcHostsParsing.cpp   Sprache: C

 

#include "gtest/gtest.h"

#include "mozilla/net/rust_helper.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
#include "nsNetUtil.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsUnicharUtils.h"
#include <fcntl.h>
#include <sys/stat.h>

#ifndef XP_WIN
#  include <sys/file.h>
#  include <unistd.h>
#endif

#ifdef XP_WIN
#  include <io.h>
#  include <share.h>
#endif

using namespace mozilla;
using namespace mozilla::net;

class TestEtcHostsParsing : public ::testing::Test {
 protected:
  void SetUp() override {
    // Get temp directory
    nsCOMPtr<nsIFile> tmpDir;
    nsresult rv =
        NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpDir));
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    // Create unique test file names
    nsAutoString baseName(u"test_hosts_");
    baseName.AppendInt(PR_IntervalNow());

    // Normal test file
    rv = tmpDir->Clone(getter_AddRefs(mTestHostsFile));
    ASSERT_TRUE(NS_SUCCEEDED(rv));
    nsAutoString normalName = baseName + u"_normal"_ns;
    rv = mTestHostsFile->Append(normalName);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    // Locked test file
    rv = tmpDir->Clone(getter_AddRefs(mLockedHostsFile));
    ASSERT_TRUE(NS_SUCCEEDED(rv));
    nsAutoString lockedName = baseName + u"_locked"_ns;
    rv = mLockedHostsFile->Append(lockedName);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    // Permission denied test file
    rv = tmpDir->Clone(getter_AddRefs(mNoPermHostsFile));
    ASSERT_TRUE(NS_SUCCEEDED(rv));
    nsAutoString noPermName = baseName + u"_noperm"_ns;
    rv = mNoPermHostsFile->Append(noPermName);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    mCallbackInvoked = false;
    mCallbackResult = true;
    mParsedHosts.Clear();
  }

  void TearDown() override {
    // Clean up test files
    if (mTestHostsFile) {
      mTestHostsFile->Remove(false);
    }
    if (mLockedHostsFile) {
      mLockedHostsFile->Remove(false);
    }
    if (mNoPermHostsFile) {
      mNoPermHostsFile->Remove(false);
    }

    // Close any open file descriptors
    if (mLockFd != -1) {
#ifdef XP_WIN
      _close(mLockFd);
#else
      close(mLockFd);
#endif
      mLockFd = -1;
    }
  }

  void CreateNormalHostsFile() {
    nsCOMPtr<nsIOutputStream> stream;
    nsresult rv =
        NS_NewLocalFileOutputStream(getter_AddRefs(stream), mTestHostsFile);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    const char* content =
        "127.0.0.1 localhost\n"
        "::1 localhost\n"
        "127.0.0.1 example.com www.example.com\n"
        "# This is a comment\n"
        "192.168.1.1 router.local\n";

    uint32_t written;
    rv = stream->Write(content, strlen(content), &written);
    ASSERT_TRUE(NS_SUCCEEDED(rv));
    ASSERT_EQ(written, strlen(content));

    rv = stream->Close();
    ASSERT_TRUE(NS_SUCCEEDED(rv));
  }

  void CreateLockedHostsFile() {
    // First create the file with content
    nsCOMPtr<nsIOutputStream> stream;
    nsresult rv =
        NS_NewLocalFileOutputStream(getter_AddRefs(stream), mLockedHostsFile);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    const char* content = "127.0.0.1 locked.test\n";
    uint32_t written;
    rv = stream->Write(content, strlen(content), &written);
    ASSERT_TRUE(NS_SUCCEEDED(rv));
    rv = stream->Close();
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    // Now lock it by opening with exclusive access
    nsAutoCString nativePath;
    rv = GetCrossplatformNativePath(mLockedHostsFile, nativePath);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

#ifdef XP_WIN
    // On Windows, open with no sharing to simulate a locked file
    mLockFd = _sopen(nativePath.get(), _O_RDONLY, _SH_DENYRW, _S_IREAD);
#else
    // On Unix, use flock to lock the file
    mLockFd = open(nativePath.get(), O_RDONLY);
    if (mLockFd != -1) {
      ::flock(mLockFd, LOCK_EX | LOCK_NB);  // Exclusive, non-blocking lock
    }
#endif
    ASSERT_NE(mLockFd, -1);
  }

  void CreateNoPermissionFile() {
#ifndef XP_WIN
    // Create the file first
    nsCOMPtr<nsIOutputStream> stream;
    nsresult rv =
        NS_NewLocalFileOutputStream(getter_AddRefs(stream), mNoPermHostsFile);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    const char* content = "127.0.0.1 noperm.test\n";
    uint32_t written;
    rv = stream->Write(content, strlen(content), &written);
    ASSERT_TRUE(NS_SUCCEEDED(rv));
    rv = stream->Close();
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    // Remove read permissions
    nsAutoCString nativePath;
    rv = GetCrossplatformNativePath(mNoPermHostsFile, nativePath);
    ASSERT_TRUE(NS_SUCCEEDED(rv));
    chmod(nativePath.get(), 0000);  // No permissions
#endif
  }

  nsresult GetCrossplatformNativePath(nsIFile* aFile, nsACString& aPath) {
#ifdef XP_WIN
    nsAutoString widePath;
    nsresult rv = aFile->GetPath(widePath);
    if (NS_FAILED(rv)) return rv;
    aPath = NS_ConvertUTF16toUTF8(widePath);
    return NS_OK;
#else
    return aFile->GetNativePath(aPath);
#endif
  }

  static bool TestCallback(const nsTArray<nsCString>* aArray) {
    auto* self = static_cast<TestEtcHostsParsing*>(sCurrentTest);
    self->mCallbackInvoked = true;

    if (aArray) {
      self->mParsedHosts.AppendElements(*aArray);
    }

    return self->mCallbackResult;
  }

  nsCOMPtr<nsIFile> mTestHostsFile;
  nsCOMPtr<nsIFile> mLockedHostsFile;
  nsCOMPtr<nsIFile> mNoPermHostsFile;
  int mLockFd = -1;

  bool mCallbackInvoked;
  bool mCallbackResult;
  nsTArray<nsCString> mParsedHosts;

  static TestEtcHostsParsing* sCurrentTest;
};

TestEtcHostsParsing* TestEtcHostsParsing::sCurrentTest = nullptr;

TEST_F(TestEtcHostsParsing, ParseNormalFile) {
  sCurrentTest = this;
  CreateNormalHostsFile();

  nsAutoCString path;
  nsresult rv = GetCrossplatformNativePath(mTestHostsFile, path);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  rust_parse_etc_hosts(&path, TestCallback);

  EXPECT_TRUE(mCallbackInvoked);
  EXPECT_GT(mParsedHosts.Length(), 0u);

  // Check that expected hostnames are parsed
  bool foundLocalhost = false;
  bool foundExampleCom = false;
  bool foundWwwExampleCom = false;
  bool foundRouterLocal = false;

  for (const auto& host : mParsedHosts) {
    if (host.EqualsLiteral("localhost")) foundLocalhost = true;
    if (host.EqualsLiteral("example.com")) foundExampleCom = true;
    if (host.EqualsLiteral("www.example.com")) foundWwwExampleCom = true;
    if (host.EqualsLiteral("router.local")) foundRouterLocal = true;
  }

  EXPECT_TRUE(foundLocalhost);
  EXPECT_TRUE(foundExampleCom);
  EXPECT_TRUE(foundWwwExampleCom);
  EXPECT_TRUE(foundRouterLocal);
}

TEST_F(TestEtcHostsParsing, ParseLockedFile) {
  sCurrentTest = this;
  CreateLockedHostsFile();

  nsAutoCString path;
  nsresult rv = GetCrossplatformNativePath(mLockedHostsFile, path);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  // The function should handle locked files gracefully and not crash or hang
  rust_parse_etc_hosts(&path, TestCallback);

  // On some systems, locked files might still be readable, on others not.
  // The important thing is that the function doesn't crash or hang.
  // We don't assert on mCallbackInvoked because it depends on platform
  // behavior.
}

TEST_F(TestEtcHostsParsing, ParseNoPermissionFile) {
#ifndef XP_WIN
  sCurrentTest = this;
  CreateNoPermissionFile();

  nsAutoCString path;
  nsresult rv = GetCrossplatformNativePath(mNoPermHostsFile, path);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  // The function should handle permission denied gracefully
  rust_parse_etc_hosts(&path, TestCallback);

  // Callback should not be invoked for files we can't read
  EXPECT_FALSE(mCallbackInvoked);
#endif
}

TEST_F(TestEtcHostsParsing, ParseNonExistentFile) {
  sCurrentTest = this;

  nsAutoCString fakePath("/nonexistent/file/hosts");

  // The function should handle non-existent files gracefully
  rust_parse_etc_hosts(&fakePath, TestCallback);

  // Callback should not be invoked for non-existent files
  EXPECT_FALSE(mCallbackInvoked);
}

TEST_F(TestEtcHostsParsing, CallbackReturnsFalse) {
  sCurrentTest = this;
  CreateNormalHostsFile();
  mCallbackResult = false;  // Tell callback to return false

  nsAutoCString path;
  nsresult rv = GetCrossplatformNativePath(mTestHostsFile, path);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  rust_parse_etc_hosts(&path, TestCallback);

  EXPECT_TRUE(mCallbackInvoked);
  // When callback returns false, parsing should stop early
  // So we shouldn't get all the hosts
}

TEST_F(TestEtcHostsParsing, EmptyFile) {
  sCurrentTest = this;

  // Create empty file
  nsCOMPtr<nsIOutputStream> stream;
  nsresult rv =
      NS_NewLocalFileOutputStream(getter_AddRefs(stream), mTestHostsFile);
  ASSERT_TRUE(NS_SUCCEEDED(rv));
  rv = stream->Close();
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  nsAutoCString path;
  rv = GetCrossplatformNativePath(mTestHostsFile, path);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  rust_parse_etc_hosts(&path, TestCallback);

  // Callback might or might not be invoked for empty files, but shouldn't crash
  EXPECT_EQ(mParsedHosts.Length(), 0u);
}

TEST_F(TestEtcHostsParsing, FileWithOnlyComments) {
  sCurrentTest = this;

  nsCOMPtr<nsIOutputStream> stream;
  nsresult rv =
      NS_NewLocalFileOutputStream(getter_AddRefs(stream), mTestHostsFile);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  const char* content =
      "# This is a comment\n"
      "# Another comment\n"
      "   # Indented comment\n";

  uint32_t written;
  rv = stream->Write(content, strlen(content), &written);
  ASSERT_TRUE(NS_SUCCEEDED(rv));
  rv = stream->Close();
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  nsAutoCString path;
  rv = GetCrossplatformNativePath(mTestHostsFile, path);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  rust_parse_etc_hosts(&path, TestCallback);

  // Should not parse any hosts from a file with only comments
  EXPECT_EQ(mParsedHosts.Length(), 0u);
}

Messung V0.5 in Prozent
C=92 H=98 G=94

¤ Dauer der Verarbeitung: 0.41 Sekunden  (vorverarbeitet am  2026-09-29) ¤

*© 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=1126864
#Domains=1897691