Skip to content
This repository has been archived by the owner on Mar 8, 2020. It is now read-only.

Commit

Permalink
expose node hashes; fixes #78
Browse files Browse the repository at this point in the history
Signed-off-by: Denys Smirnov <denys@sourced.tech>
  • Loading branch information
Denys Smirnov committed Jul 9, 2019
1 parent 6086f5a commit 139a628
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/libuast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ namespace uast {
virtual T node() = 0;
};

// NodeHash is a hash of a node subtree.
struct NodeHash {
// The data are a cryptographic-quality fingerprint of the tree structure.
// The specific algorithm is not specified and may change across library versions.
// Clients may compare hash values for equality to match equivalent nodes, but cannot
// recompute hash values directly, as the input depends on details of serialization.
uint8_t data[UAST_HASH_SIZE];
};

// Context is a common interface implemented by all UAST contexts.
template<class T> class Context {
public:
Expand All @@ -75,6 +84,7 @@ namespace uast {

virtual Iterator<T>* Filter(T root, std::string query) = 0;
virtual Iterator<T>* Iterate(T root, TreeOrder order) = 0;
virtual NodeHash Hash(T root, HashFlags flags) = 0;
};

// NodeCreator is an interface that creates new UAST nodes.
Expand Down Expand Up @@ -351,6 +361,11 @@ namespace uast {
CheckError();
return new RawIterator(it);
}
NodeHash Hash(NodeHandle root, HashFlags flags) {
NodeHash h;
UastHash(ctx, root, (void*)&h, flags);
return h;
}
};

// PtrIterator is an iterator that casts NodeHandle directly to pointer type T.
Expand Down Expand Up @@ -414,6 +429,9 @@ namespace uast {
auto it = new PtrIterator<T>(raw, true);
return it;
}
NodeHash Hash(T root, HashFlags flags) {
return ctx->Hash(ToHandle(root), flags);
}
void CheckError(){
ctx->CheckError();
}
Expand Down
2 changes: 2 additions & 0 deletions src/uast.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ typedef struct UastIterator {

typedef enum { UAST_BINARY = 0, UAST_YAML = 1 } UastFormat;

// HashFlags is a bit-field with different flags which controls node hashing.
typedef enum {
HASH_ALL = 0x0,
HASH_NO_POS = 0x1,
} HashFlags;

Expand Down
1 change: 1 addition & 0 deletions tests/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int main() {

// add the tests to the suite
ADD_TEST(suite, "test of RoleNameForId()", TestRoleNameForId);
ADD_TEST(suite, "test node hash", TestNodeHash);
ADD_TEST(suite, "test of UastFilter() pointers", TestUastFilterPointers);
ADD_TEST(suite, "test iteration (preorder)", TestUastIteratorPreOrder);
ADD_TEST(suite, "test of UastFilter() counting", TestUastFilterCount);
Expand Down
30 changes: 30 additions & 0 deletions tests/nodes_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,36 @@ void TestNodeFindError() {
UastFree(ctx);
}

void TestNodeHash() {
Uast *ctx = NewUastMock();
Node* module = newObject("Module");
Node* child = newObject("Child");
module->SetChild("field", child);

unsigned char hash[UAST_HASH_SIZE];
// This value must be updated if the algorithm for structural hashing is changed,
// or if the tree structure for the test module changes in a way that modifies the
// structural hash. To update it, copy the actual value from the test failure and
// update this array.
unsigned char exp[UAST_HASH_SIZE] = {
0xe6, 0xd2, 0x53, 0xe1, 0x26, 0x0a, 0xaa, 0xa9,
0x37, 0xcc, 0xfc, 0x42, 0x0f, 0x52, 0x65, 0x48,
0x1d, 0x59, 0x18, 0xce, 0x01, 0xad, 0xda, 0xa2,
0x82, 0x4c, 0x74, 0x77, 0xae, 0xa1, 0x26, 0xb5};
UastHash(ctx, NodeHandle(module), (void*)hash, HASH_ALL);
bool ok = memcmp(hash, exp, UAST_HASH_SIZE) == 0;
if (!ok) {
printf("unexpected hash value:\n");
for (int i = 0; i < UAST_HASH_SIZE; i++) {
printf("0x%02x, ", (unsigned char)hash[i]);
if (i%8 == 7) printf("\n");
}
}
CU_ASSERT_FATAL(ok);

UastFree(ctx);
}

void TestEmptyResult() {
Uast *ctx = NewUastMock();
Node* module = newObject("Module");
Expand Down

0 comments on commit 139a628

Please sign in to comment.