コード例 #1
0
ファイル: TestJson.c プロジェクト: rectang/lucy
static void
test_numbers(TestBatchRunner *runner) {
    Integer *i64     = Int_new(33);
    String  *json    = Json_to_json((Obj*)i64);
    String  *trimmed = Str_Trim(json);
    TEST_TRUE(runner, Str_Equals_Utf8(trimmed, "33", 2), "Integer");
    DECREF(json);
    DECREF(trimmed);

    Float *f64 = Float_new(33.33);
    json = Json_to_json((Obj*)f64);
    if (json) {
        double value = Str_To_F64(json);
        double diff = 33.33 - value;
        if (diff < 0.0) { diff = 0.0 - diff; }
        TEST_TRUE(runner, diff < 0.0001, "Float");
        DECREF(json);
    }
    else {
        FAIL(runner, "Float conversion to  json  failed.");
    }

    DECREF(i64);
    DECREF(f64);
}
コード例 #2
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
test_escapes(TestBatch *batch) {
    CharBuf *string      = CB_new(10);
    CharBuf *json_wanted = CB_new(10);

    for (int i = 0; control_escapes[i] != NULL; i++) {
        CB_Truncate(string, 0);
        CB_Cat_Char(string, i);
        const char *escaped = control_escapes[i];
        CharBuf    *json    = Json_to_json((Obj*)string);
        CharBuf    *decoded = (CharBuf*)Json_from_json(json);

        CB_setf(json_wanted, "\"%s\"", escaped);
        CB_Trim(json);
        TEST_TRUE(batch, json != NULL && CB_Equals(json_wanted, (Obj*)json),
                  "encode control escape: %s", escaped);

        TEST_TRUE(batch, decoded != NULL && CB_Equals(string, (Obj*)decoded),
                  "decode control escape: %s", escaped);

        DECREF(json);
        DECREF(decoded);
    }

    for (int i = 0; quote_escapes_source[i] != NULL; i++) {
        const char *source  = quote_escapes_source[i];
        const char *escaped = quote_escapes_json[i];
        CB_setf(string, source, strlen(source));
        CharBuf *json    = Json_to_json((Obj*)string);
        CharBuf *decoded = (CharBuf*)Json_from_json(json);

        CB_setf(json_wanted, "\"%s\"", escaped);
        CB_Trim(json);
        TEST_TRUE(batch, json != NULL && CB_Equals(json_wanted, (Obj*)json),
                  "encode quote/backslash escapes: %s", source);

        TEST_TRUE(batch, decoded != NULL && CB_Equals(string, (Obj*)decoded),
                  "decode quote/backslash escapes: %s", source);

        DECREF(json);
        DECREF(decoded);
    }

    DECREF(json_wanted);
    DECREF(string);
}
コード例 #3
0
ファイル: TestJson.c プロジェクト: rectang/lucy
static void
test_escapes(TestBatchRunner *runner) {
    for (int i = 0; control_escapes[i] != NULL; i++) {
        String     *string  = Str_new_from_char(i);
        const char *escaped = control_escapes[i];
        String     *json    = Json_to_json((Obj*)string);
        String     *trimmed = Str_Trim(json);
        String     *decoded = (String*)Json_from_json(json);

        String *json_wanted = Str_newf("\"%s\"", escaped);
        TEST_TRUE(runner, Str_Equals(json_wanted, (Obj*)trimmed),
                  "encode control escape: %s", escaped);

        TEST_TRUE(runner, decoded != NULL && Str_Equals(string, (Obj*)decoded),
                  "decode control escape: %s", escaped);

        DECREF(string);
        DECREF(json);
        DECREF(trimmed);
        DECREF(decoded);
        DECREF(json_wanted);
    }

    for (int i = 0; quote_escapes_source[i] != NULL; i++) {
        const char *source  = quote_escapes_source[i];
        const char *escaped = quote_escapes_json[i];
        String *string  = Str_new_from_utf8(source, strlen(source));
        String *json    = Json_to_json((Obj*)string);
        String *trimmed = Str_Trim(json);
        String *decoded = (String*)Json_from_json(json);

        String *json_wanted = Str_newf("\"%s\"", escaped);
        TEST_TRUE(runner, Str_Equals(json_wanted, (Obj*)trimmed),
                  "encode quote/backslash escapes: %s", source);

        TEST_TRUE(runner, decoded != NULL && Str_Equals(string, (Obj*)decoded),
                  "decode quote/backslash escapes: %s", source);

        DECREF(string);
        DECREF(json);
        DECREF(trimmed);
        DECREF(decoded);
        DECREF(json_wanted);
    }
}
コード例 #4
0
ファイル: TestJson.c プロジェクト: rectang/lucy
static void
test_tolerance(TestBatchRunner *runner) {
    String *foo = Str_newf("foo");
    String *not_json = Json_to_json((Obj*)foo);
    TEST_TRUE(runner, not_json == NULL,
              "to_json returns NULL when fed invalid data type");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "to_json sets global error when fed invalid data type");
    DECREF(foo);
}
コード例 #5
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
test_tolerance(TestBatch *batch) {
    CharBuf *foo = CB_newf("foo");
    CharBuf *not_json = Json_to_json((Obj*)foo);
    TEST_TRUE(batch, not_json == NULL,
              "to_json returns NULL when fed invalid data type");
    TEST_TRUE(batch, Err_get_error() != NULL,
              "to_json sets Err_error when fed invalid data type");
    DECREF(foo);
}
コード例 #6
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
test_to_and_from(TestBatch *batch) {
    Obj *dump = S_make_dump();
    CharBuf *json = Json_to_json(dump);
    Obj *got = Json_from_json(json);
    TEST_TRUE(batch, got != NULL && Obj_Equals(dump, got),
              "Round trip through to_json and from_json");
    DECREF(dump);
    DECREF(json);
    DECREF(got);
}
コード例 #7
0
ファイル: TestJson.c プロジェクト: rectang/lucy
static void
test_to_and_from(TestBatchRunner *runner) {
    Obj *dump = S_make_dump();
    String *json = Json_to_json(dump);
    Obj *got = Json_from_json(json);
    TEST_TRUE(runner, got != NULL && Obj_Equals(dump, got),
              "Round trip through to_json and from_json");
    DECREF(dump);
    DECREF(json);
    DECREF(got);
}
コード例 #8
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
test_max_depth(TestBatch *batch) {
    Hash *circular = Hash_new(0);
    Hash_Store_Str(circular, "circular", 8, INCREF(circular));
    Err_set_error(NULL);
    CharBuf *not_json = Json_to_json((Obj*)circular);
    TEST_TRUE(batch, not_json == NULL,
              "to_json returns NULL when fed recursing data");
    TEST_TRUE(batch, Err_get_error() != NULL,
              "to_json sets Err_error when fed recursing data");
    DECREF(Hash_Delete_Str(circular, "circular", 8));
    DECREF(circular);
}
コード例 #9
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
S_round_trip_integer(TestBatch *batch, int64_t value) {
    Integer64 *num = Int64_new(value);
    VArray *array = VA_new(1);
    VA_Store(array, 0, (Obj*)num);
    CharBuf *json = Json_to_json((Obj*)array);
    Obj *dump = Json_from_json(json);
    TEST_TRUE(batch, VA_Equals(array, dump), "Round trip integer %ld",
              (long)value);
    DECREF(dump);
    DECREF(json);
    DECREF(array);
}
コード例 #10
0
ファイル: TestJson.c プロジェクト: rectang/lucy
static void
test_max_depth(TestBatchRunner *runner) {
    Hash *circular = Hash_new(0);
    Hash_Store_Utf8(circular, "circular", 8, INCREF(circular));
    Err_set_error(NULL);
    String *not_json = Json_to_json((Obj*)circular);
    TEST_TRUE(runner, not_json == NULL,
              "to_json returns NULL when fed recursing data");
    TEST_TRUE(runner, Err_get_error() != NULL,
              "to_json sets global error when fed recursing data");
    DECREF(Hash_Delete_Utf8(circular, "circular", 8));
    DECREF(circular);
}
コード例 #11
0
ファイル: TestJson.c プロジェクト: rectang/lucy
static void
S_round_trip_integer(TestBatchRunner *runner, int64_t value) {
    Integer *num = Int_new(value);
    Vector *array = Vec_new(1);
    Vec_Store(array, 0, (Obj*)num);
    String *json = Json_to_json((Obj*)array);
    Obj *dump = Json_from_json(json);
    TEST_TRUE(runner, Vec_Equals(array, dump), "Round trip integer %ld",
              (long)value);
    DECREF(dump);
    DECREF(json);
    DECREF(array);
}
コード例 #12
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
test_illegal_keys(TestBatch *batch) {
    Hash *hash = Hash_new(0);
    Float64 *key = Float64_new(1.1);
    Hash_Store(hash, (Obj*)key, (Obj*)CB_newf("blah"));
    Err_set_error(NULL);
    CharBuf *not_json = Json_to_json((Obj*)hash);
    TEST_TRUE(batch, not_json == NULL,
              "to_json returns NULL when fed an illegal key");
    TEST_TRUE(batch, Err_get_error() != NULL,
              "to_json sets Err_error when fed an illegal key");
    DECREF(key);
    DECREF(hash);
}
コード例 #13
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
S_round_trip_float(TestBatch *batch, double value, double max_diff) {
    Float64 *num = Float64_new(value);
    VArray *array = VA_new(1);
    VA_Store(array, 0, (Obj*)num);
    CharBuf *json = Json_to_json((Obj*)array);
    Obj *dump = CERTIFY(Json_from_json(json), VARRAY);
    Float64 *got = (Float64*)CERTIFY(VA_Fetch((VArray*)dump, 0), FLOAT64);
    double diff = Float64_Get_Value(num) - Float64_Get_Value(got);
    if (diff < 0) { diff = 0 - diff; }
    TEST_TRUE(batch, diff <= max_diff, "Round trip float %f", value);
    DECREF(dump);
    DECREF(json);
    DECREF(array);
}
コード例 #14
0
ファイル: TestJson.c プロジェクト: pavansondur/lucy
static void
test_numbers(TestBatch *batch) {
    Integer64 *i64  = Int64_new(33);
    CharBuf   *json = Json_to_json((Obj*)i64);
    CB_Trim(json);
    TEST_TRUE(batch, json && CB_Equals_Str(json, "33", 2), "Integer");
    DECREF(json);

    Float64 *f64 = Float64_new(33.33);
    json = Json_to_json((Obj*)f64);
    if (json) {
        double value = CB_To_F64(json);
        double diff = 33.33 - value;
        if (diff < 0.0) { diff = 0.0 - diff; }
        TEST_TRUE(batch, diff < 0.0001, "Float");
        DECREF(json);
    }
    else {
        FAIL(batch, "Float conversion to  json  failed.");
    }

    DECREF(i64);
    DECREF(f64);
}
コード例 #15
0
ファイル: TestJson.c プロジェクト: rectang/lucy
static void
S_round_trip_float(TestBatchRunner *runner, double value, double max_diff) {
    Float *num = Float_new(value);
    Vector *array = Vec_new(1);
    Vec_Store(array, 0, (Obj*)num);
    String *json = Json_to_json((Obj*)array);
    Obj *dump = CERTIFY(Json_from_json(json), VECTOR);
    Float *got = (Float*)CERTIFY(Vec_Fetch((Vector*)dump, 0), FLOAT);
    double diff = Float_Get_Value(num) - Float_Get_Value(got);
    if (diff < 0) { diff = 0 - diff; }
    TEST_TRUE(runner, diff <= max_diff, "Round trip float %f", value);
    DECREF(dump);
    DECREF(json);
    DECREF(array);
}
コード例 #16
0
ファイル: Json.c プロジェクト: pavansondur/lucy
bool_t
Json_spew_json(Obj *dump, Folder *folder, const CharBuf *path) {
    CharBuf *json = Json_to_json(dump);
    if (!json) {
        ERR_ADD_FRAME(Err_get_error());
        return false;
    }
    OutStream *outstream = Folder_Open_Out(folder, path);
    if (!outstream) {
        ERR_ADD_FRAME(Err_get_error());
        DECREF(json);
        return false;
    }
    size_t size = CB_Get_Size(json);
    OutStream_Write_Bytes(outstream, CB_Get_Ptr8(json), size);
    OutStream_Close(outstream);
    DECREF(outstream);
    DECREF(json);
    return true;
}
コード例 #17
0
ファイル: Lock.c プロジェクト: carriercomm/lucy
bool
LFLock_Request_IMP(LockFileLock *self) {
    LockFileLockIVARS *const ivars = LFLock_IVARS(self);
    bool success = false;

    if (Folder_Exists(ivars->folder, ivars->lock_path)) {
        Err_set_error((Err*)LockErr_new(Str_newf("Can't obtain lock: '%o' exists",
                                                 ivars->lock_path)));
        return false;
    }

    // Create the "locks" subdirectory if necessary.
    String *lock_dir_name = (String*)SSTR_WRAP_UTF8("locks", 5);
    if (!Folder_Exists(ivars->folder, lock_dir_name)) {
        if (!Folder_MkDir(ivars->folder, lock_dir_name)) {
            Err *mkdir_err = (Err*)CERTIFY(Err_get_error(), ERR);
            LockErr *err = LockErr_new(Str_newf("Can't create 'locks' directory: %o",
                                                Err_Get_Mess(mkdir_err)));
            // Maybe our attempt failed because another process succeeded.
            if (Folder_Find_Folder(ivars->folder, lock_dir_name)) {
                DECREF(err);
            }
            else {
                // Nope, everything failed, so bail out.
                Err_set_error((Err*)err);
                return false;
            }
        }
    }

    // Prepare to write pid, lock name, and host to the lock file as JSON.
    Hash *file_data = Hash_new(3);
    Hash_Store_Utf8(file_data, "pid", 3,
                    (Obj*)Str_newf("%i32", (int32_t)PID_getpid()));
    Hash_Store_Utf8(file_data, "host", 4, INCREF(ivars->host));
    Hash_Store_Utf8(file_data, "name", 4, INCREF(ivars->name));
    String *json = Json_to_json((Obj*)file_data);
    DECREF(file_data);

    // Write to a temporary file, then use the creation of a hard link to
    // ensure atomic but non-destructive creation of the lockfile with its
    // complete contents.

    OutStream *outstream = Folder_Open_Out(ivars->folder, ivars->link_path);
    if (!outstream) {
        ERR_ADD_FRAME(Err_get_error());
        DECREF(json);
        return false;
    }

    struct lockfile_context context;
    context.outstream = outstream;
    context.json = json;
    Err *json_error = Err_trap(S_write_lockfile_json, &context);
    bool wrote_json = !json_error;
    DECREF(outstream);
    DECREF(json);
    if (wrote_json) {
        success = Folder_Hard_Link(ivars->folder, ivars->link_path,
                                   ivars->lock_path);
        if (!success) {
            Err *hard_link_err = (Err*)CERTIFY(Err_get_error(), ERR);
            Err_set_error((Err*)LockErr_new(Str_newf("Failed to obtain lock at '%o': %o",
                                                     ivars->lock_path,
                                                     Err_Get_Mess(hard_link_err))));
        }
    }
    else {
        Err_set_error((Err*)LockErr_new(Str_newf("Failed to obtain lock at '%o': %o",
                                                 ivars->lock_path,
                                                 Err_Get_Mess(json_error))));
        DECREF(json_error);
    }

    // Verify that our temporary file got zapped.
    bool deletion_failed = !Folder_Delete(ivars->folder, ivars->link_path);
    if (deletion_failed) {
        String *mess = MAKE_MESS("Failed to delete '%o'", ivars->link_path);
        Err_throw_mess(ERR, mess);
    }

    return success;
}