Initial Contribution
diff --git a/amend/test_permissions.c b/amend/test_permissions.c
new file mode 100644
index 0000000..c389456
--- /dev/null
+++ b/amend/test_permissions.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#undef NDEBUG
+#include <assert.h>
+#include "permissions.h"
+
+static int
+test_permission_list()
+{
+    PermissionRequestList list;
+    int ret;
+    int numRequests;
+
+    /* Bad parameter
+     */
+    ret = initPermissionRequestList(NULL);
+    assert(ret < 0);
+
+    /* Good parameter
+     */
+    ret = initPermissionRequestList(&list);
+    assert(ret == 0);
+
+    /* Bad parameters
+     */
+    ret = addPermissionRequestToList(NULL, NULL, false, 0);
+    assert(ret < 0);
+
+    ret = addPermissionRequestToList(&list, NULL, false, 0);
+    assert(ret < 0);
+
+    /* Good parameters
+     */
+    numRequests = 0;
+
+    ret = addPermissionRequestToList(&list, "one", false, 1);
+    assert(ret == 0);
+    numRequests++;
+
+    ret = addPermissionRequestToList(&list, "two", false, 2);
+    assert(ret == 0);
+    numRequests++;
+
+    ret = addPermissionRequestToList(&list, "three", false, 3);
+    assert(ret == 0);
+    numRequests++;
+
+    ret = addPermissionRequestToList(&list, "recursive", true, 55);
+    assert(ret == 0);
+    numRequests++;
+
+    /* Validate the list
+     */
+    assert(list.requests != NULL);
+    assert(list.numRequests == numRequests);
+    assert(list.numRequests <= list.requestsAllocated);
+    bool sawOne = false;
+    bool sawTwo = false;
+    bool sawThree = false;
+    bool sawRecursive = false;
+    int i;
+    for (i = 0; i < list.numRequests; i++) {
+        PermissionRequest *req = &list.requests[i];
+        assert(req->allowed == 0);
+
+        /* Order isn't guaranteed, so we have to switch every time.
+         */
+        if (strcmp(req->path, "one") == 0) {
+            assert(!sawOne);
+            assert(req->requested == 1);
+            assert(!req->recursive);
+            sawOne = true;
+        } else if (strcmp(req->path, "two") == 0) {
+            assert(!sawTwo);
+            assert(req->requested == 2);
+            assert(!req->recursive);
+            sawTwo = true;
+        } else if (strcmp(req->path, "three") == 0) {
+            assert(!sawThree);
+            assert(req->requested == 3);
+            assert(!req->recursive);
+            sawThree = true;
+        } else if (strcmp(req->path, "recursive") == 0) {
+            assert(!sawRecursive);
+            assert(req->requested == 55);
+            assert(req->recursive);
+            sawRecursive = true;
+        } else {
+            assert(false);
+        }
+    }
+    assert(sawOne);
+    assert(sawTwo);
+    assert(sawThree);
+    assert(sawRecursive);
+
+    /* Smoke test the teardown
+     */
+    freePermissionRequestListElements(&list);
+
+    return 0;
+}
+
+static int
+test_permission_table()
+{
+    int ret;
+
+    /* Test the global permissions table.
+     * Try calling functions without initializing first.
+     */
+    ret = registerPermissionSet(0, NULL);
+    assert(ret < 0);
+
+    ret = countPermissionConflicts((PermissionRequestList *)16, false);
+    assert(ret < 0);
+
+    ret = getPermissionCount();
+    assert(ret < 0);
+
+    const Permission *p;
+    p = getPermissionAt(0);
+    assert(p == NULL);
+
+    /* Initialize.
+     */
+    ret = permissionInit();
+    assert(ret == 0);
+
+    /* Make sure we can't initialize twice.
+     */
+    ret = permissionInit();
+    assert(ret < 0);
+
+    /* Test the inspection functions.
+     */
+    ret = getPermissionCount();
+    assert(ret == 0);
+
+    p = getPermissionAt(-1);
+    assert(p == NULL);
+
+    p = getPermissionAt(0);
+    assert(p == NULL);
+
+    p = getPermissionAt(1);
+    assert(p == NULL);
+
+    /* Test registerPermissionSet().
+     * Try some bad parameter values.
+     */
+    ret = registerPermissionSet(-1, NULL);
+    assert(ret < 0);
+
+    ret = registerPermissionSet(1, NULL);
+    assert(ret < 0);
+
+    /* Register some permissions.
+     */
+    Permission p1;
+    p1.path = "one";
+    p1.allowed = 1;
+    ret = registerPermissionSet(1, &p1);
+    assert(ret == 0);
+    ret = getPermissionCount();
+    assert(ret == 1);
+
+    Permission p2[2];
+    p2[0].path = "two";
+    p2[0].allowed = 2;
+    p2[1].path = "three";
+    p2[1].allowed = 3;
+    ret = registerPermissionSet(2, p2);
+    assert(ret == 0);
+    ret = getPermissionCount();
+    assert(ret == 3);
+
+    ret = registerPermissionSet(0, NULL);
+    assert(ret == 0);
+    ret = getPermissionCount();
+    assert(ret == 3);
+
+    p1.path = "four";
+    p1.allowed = 4;
+    ret = registerPermissionSet(1, &p1);
+    assert(ret == 0);
+
+    /* Make sure the table looks correct.
+     * Order is important;  more-recent additions
+     * should appear at higher indices.
+     */
+    ret = getPermissionCount();
+    assert(ret == 4);
+
+    int i;
+    for (i = 0; i < ret; i++) {
+        const Permission *p;
+        p = getPermissionAt(i);
+        assert(p != NULL);
+        assert(p->allowed == (unsigned int)(i + 1));
+        switch (i) {
+        case 0:
+            assert(strcmp(p->path, "one") == 0);
+            break;
+        case 1:
+            assert(strcmp(p->path, "two") == 0);
+            break;
+        case 2:
+            assert(strcmp(p->path, "three") == 0);
+            break;
+        case 3:
+            assert(strcmp(p->path, "four") == 0);
+            break;
+        default:
+            assert(!"internal error");
+            break;
+        }
+    }
+    p = getPermissionAt(ret);
+    assert(p == NULL);
+
+    /* Smoke test the teardown
+     */
+    permissionCleanup();
+
+    return 0;
+}
+
+static int
+test_allowed_permissions()
+{
+    int ret;
+    int numPerms;
+
+    /* Make sure these fail before initialization.
+     */
+    ret = countPermissionConflicts((PermissionRequestList *)1, false);
+    assert(ret < 0);
+
+    ret = getAllowedPermissions((const char *)1, false, (unsigned int *)1);
+    assert(ret < 0);
+
+    /* Initialize.
+     */
+    ret = permissionInit();
+    assert(ret == 0);
+
+    /* Make sure countPermissionConflicts() fails with bad parameters.
+     */
+    ret = countPermissionConflicts(NULL, false);
+    assert(ret < 0);
+
+    /* Register a set of permissions.
+     */
+    Permission perms[] = {
+        { "/", PERM_NONE },
+        { "/stat", PERM_STAT },
+        { "/read", PERMSET_READ },
+        { "/write", PERMSET_WRITE },
+        { "/.stat", PERM_STAT },
+        { "/.stat/.read", PERMSET_READ },
+        { "/.stat/.read/.write", PERMSET_WRITE },
+        { "/.stat/.write", PERMSET_WRITE },
+    };
+    numPerms = sizeof(perms) / sizeof(perms[0]);
+    ret = registerPermissionSet(numPerms, perms);
+    assert(ret == 0);
+
+    /* Build a permission request list.
+     */
+    PermissionRequestList list;
+    ret = initPermissionRequestList(&list);
+    assert(ret == 0);
+
+    ret = addPermissionRequestToList(&list, "/stat", false, PERM_STAT);
+    assert(ret == 0);
+
+    ret = addPermissionRequestToList(&list, "/read", false, PERM_READ);
+    assert(ret == 0);
+
+    ret = addPermissionRequestToList(&list, "/write", false, PERM_WRITE);
+    assert(ret == 0);
+
+    //TODO: cover more cases once the permission stuff has been implemented
+
+    /* All of the requests in the list should be allowed.
+     */
+    ret = countPermissionConflicts(&list, false);
+    assert(ret == 0);
+
+    /* Add a request that will be denied.
+     */
+    ret = addPermissionRequestToList(&list, "/stat", false, 1<<31 | PERM_STAT);
+    assert(ret == 0);
+
+    ret = countPermissionConflicts(&list, false);
+    assert(ret == 1);
+
+    //TODO: more tests
+
+    permissionCleanup();
+
+    return 0;
+}
+
+int
+test_permissions()
+{
+    int ret;
+
+    ret = test_permission_list();
+    if (ret != 0) {
+        fprintf(stderr, "test_permission_list() failed: %d\n", ret);
+        return ret;
+    }
+
+    ret = test_permission_table();
+    if (ret != 0) {
+        fprintf(stderr, "test_permission_table() failed: %d\n", ret);
+        return ret;
+    }
+
+    ret = test_allowed_permissions();
+    if (ret != 0) {
+        fprintf(stderr, "test_permission_table() failed: %d\n", ret);
+        return ret;
+    }
+
+    return 0;
+}