test(tvix): Cover scanForReferences in a test
Aded a few test cases covering the scanForReferences function, which had
been accidentally broken in 976a36c (which is now partially-reverted).
As part of this, since the test needed to generate hashes for store
paths, the logic in MakeStorePath to compress a sha256 hash down to 20
bytes and convert it to base32 has been extracted to a member function
on the Hash class.
Fixes: #34
Change-Id: Ie2d914688a80f42d0234d351a7cc0714fd15709e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1698
Tested-by: BuildkiteCI
Reviewed-by: kanepyork <rikingcoding@gmail.com>
			
			
This commit is contained in:
		
							parent
							
								
									dfab786653
								
							
						
					
					
						commit
						d1653533a6
					
				
					 6 changed files with 98 additions and 5 deletions
				
			
		
							
								
								
									
										5
									
								
								third_party/nix/src/libstore/store-api.cc
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								third_party/nix/src/libstore/store-api.cc
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -323,9 +323,8 @@ Path Store::makeStorePath(const std::string& type, const Hash& hash,
 | 
			
		|||
 | 
			
		||||
  checkStoreName(name);
 | 
			
		||||
 | 
			
		||||
  return storeDir + "/" +
 | 
			
		||||
         compressHash(hashString(htSHA256, s), 20).to_string(Base32, false) +
 | 
			
		||||
         "-" + name;
 | 
			
		||||
  return absl::StrCat(storeDir, "/", hashString(htSHA256, s).ToStorePathHash(),
 | 
			
		||||
                      "-", name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Path Store::makeOutputPath(const std::string& id, const Hash& hash,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								third_party/nix/src/libutil/hash.cc
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								third_party/nix/src/libutil/hash.cc
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -158,6 +158,10 @@ bool Hash::IsValidBase32(absl::string_view s) {
 | 
			
		|||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string Hash::ToStorePathHash() const {
 | 
			
		||||
  return compressHash(*this, kStorePathHashSize).to_string(Base32, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static std::string printHash32(const Hash& hash) {
 | 
			
		||||
  assert(hash.hashSize);
 | 
			
		||||
  size_t len = hash.base32Len();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								third_party/nix/src/libutil/hash.hh
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								third_party/nix/src/libutil/hash.hh
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -8,6 +8,9 @@
 | 
			
		|||
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
// Size of the hashes rendered in store paths, in bytes
 | 
			
		||||
constexpr unsigned int kStorePathHashSize = 20;
 | 
			
		||||
 | 
			
		||||
MakeError(BadHash, Error);
 | 
			
		||||
 | 
			
		||||
// TODO(grfn): Replace this with the hash type enum from the daemon proto so we
 | 
			
		||||
| 
						 | 
				
			
			@ -90,6 +93,9 @@ struct Hash {
 | 
			
		|||
  /* Returns whether the passed string contains entirely valid base32
 | 
			
		||||
     characters. */
 | 
			
		||||
  static bool IsValidBase32(absl::string_view s);
 | 
			
		||||
 | 
			
		||||
  // Convert this Hash to the format expected in store paths
 | 
			
		||||
  [[nodiscard]] std::string ToStorePathHash() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Print a hash in base-16 if it's MD5, or base-32 otherwise. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								third_party/nix/src/nix/hash.cc
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								third_party/nix/src/nix/hash.cc
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -36,8 +36,8 @@ struct CmdHash final : Command {
 | 
			
		|||
  void run() override {
 | 
			
		||||
    for (const auto& path : paths) {
 | 
			
		||||
      Hash h = mode == mFile ? hashFile(ht, path) : hashPath(ht, path).first;
 | 
			
		||||
      if (truncate && h.hashSize > 20) {
 | 
			
		||||
        h = compressHash(h, 20);
 | 
			
		||||
      if (truncate && h.hashSize > nix::kStorePathHashSize) {
 | 
			
		||||
        h = compressHash(h, nix::kStorePathHashSize);
 | 
			
		||||
      }
 | 
			
		||||
      std::cout << format("%1%\n") % h.to_string(base, base == SRI);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								third_party/nix/src/tests/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								third_party/nix/src/tests/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -30,6 +30,16 @@ target_link_libraries(hash_test
 | 
			
		|||
 | 
			
		||||
gtest_discover_tests(hash_test)
 | 
			
		||||
 | 
			
		||||
add_executable(references_test references_test.cc)
 | 
			
		||||
target_link_libraries(references_test
 | 
			
		||||
  nixstore
 | 
			
		||||
  rapidcheck
 | 
			
		||||
  rapidcheck_gtest
 | 
			
		||||
  GTest::gtest_main
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
gtest_discover_tests(references_test)
 | 
			
		||||
 | 
			
		||||
add_executable(store_test store_tests.cc)
 | 
			
		||||
target_link_libraries(store_test
 | 
			
		||||
  nixstore
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										74
									
								
								third_party/nix/src/tests/references_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								third_party/nix/src/tests/references_test.cc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
#include "libstore/references.hh"
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
 | 
			
		||||
#include <absl/strings/str_format.h>
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
#include <rapidcheck.h>
 | 
			
		||||
#include <rapidcheck/gtest.h>
 | 
			
		||||
 | 
			
		||||
#include "libutil/hash.hh"
 | 
			
		||||
 | 
			
		||||
class ReferencesTest : public ::testing::Test {};
 | 
			
		||||
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
TEST(ReferencesTest, ScanForOneReferenceNotFound) {
 | 
			
		||||
  char path[] = "store_XXXXXXX";
 | 
			
		||||
  auto f = mkstemp(path);
 | 
			
		||||
 | 
			
		||||
  auto hash = hashString(htSHA256, "foo");
 | 
			
		||||
  auto ref = absl::StrFormat("/nix/store/%s-foo", hash.ToStorePathHash());
 | 
			
		||||
 | 
			
		||||
  HashResult hr;
 | 
			
		||||
  auto result = scanForReferences(path, {ref}, hr);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(result.find(ref), result.end());
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(close(f), 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ReferencesTest, ScanForOneReferenceFound) {
 | 
			
		||||
  char path[] = "store_XXXXXXX";
 | 
			
		||||
  auto f = mkstemp(path);
 | 
			
		||||
 | 
			
		||||
  auto hash = hashString(htSHA256, "foo");
 | 
			
		||||
  auto ref = absl::StrFormat("/nix/store/%s-foo", hash.ToStorePathHash());
 | 
			
		||||
 | 
			
		||||
  EXPECT_GT(write(f, ref.c_str(), sizeof(char) * ref.size()), 0);
 | 
			
		||||
 | 
			
		||||
  HashResult hr;
 | 
			
		||||
  auto result = scanForReferences(path, {ref}, hr);
 | 
			
		||||
 | 
			
		||||
  ASSERT_NE(result.find(ref), result.end());
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(close(f), 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RC_GTEST_PROP(ReferencesTest, ScanForReferences,
 | 
			
		||||
              (std::unordered_set<std::string> strs)) {
 | 
			
		||||
  char path[] = "store_XXXXXXX";
 | 
			
		||||
  auto f = mkstemp(path);
 | 
			
		||||
 | 
			
		||||
  PathSet refs;
 | 
			
		||||
  for (const auto& s : strs) {
 | 
			
		||||
    auto hash = hashString(htSHA256, s);
 | 
			
		||||
    auto ref = absl::StrFormat("/nix/store/%s-foo", hash.ToStorePathHash());
 | 
			
		||||
    refs.insert(ref);
 | 
			
		||||
    RC_ASSERT(write(f, ref.c_str(), sizeof(char) * ref.size()) > 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  HashResult hr;
 | 
			
		||||
  auto result = scanForReferences(path, refs, hr);
 | 
			
		||||
 | 
			
		||||
  for (const auto& ref : refs) {
 | 
			
		||||
    RC_ASSERT(result.find(ref) != result.end());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  RC_ASSERT(close(f) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace nix
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue