void testWrite(dmlite_context* context) { dmlite_fd* file; dmlite_any_dict* dict = dmlite_any_dict_new(); char buffer[64]; SECTION("Read"); /* Good to open */ dmlite_any* token = dmlite_any_new_string("987654321"); dmlite_any_dict_insert(dict, "token", token); dmlite_any_free(token); TEST_CONTEXT_CALL_PTR(file, context, dmlite_fopen, "/file", O_RDWR, dict); /* Write a chunk */ TEST_ASSERT_EQUAL(10, dmlite_fwrite(file, "123456789", 10)); /* Seek and read it back */ TEST_ASSERT_EQUAL(0, dmlite_fseek(file, 0, SEEK_SET)); TEST_ASSERT_EQUAL(10, dmlite_fread(file, buffer, 10)); TEST_ASSERT_STR_EQUAL("123456789", buffer); /* Free */ TEST_ASSERT_EQUAL(0, dmlite_fclose(file)); dmlite_any_dict_free(dict); }
void testRead(dmlite_context* context) { dmlite_fd* file; dmlite_any_dict* dict = dmlite_any_dict_new(); char buffer[64]; memset(buffer, 0, sizeof(buffer)); SECTION("Read"); /* Bad token */ file = dmlite_fopen(context, "/file", O_RDONLY, dict); TEST_ASSERT_EQUAL(NULL, file); TEST_ASSERT_EQUAL(DM_FORBIDDEN, dmlite_errno(context)); /* Open non-existing */ file = dmlite_fopen(context, "/does-not-exist", O_RDONLY, dict); TEST_ASSERT_EQUAL(NULL, file); TEST_ASSERT_EQUAL(DM_NO_SUCH_FILE, dmlite_errno(context)); /* Good to open */ dmlite_any* token = dmlite_any_new_string("123456789"); dmlite_any_dict_insert(dict, "token", token); dmlite_any_free(token); TEST_CONTEXT_CALL_PTR(file, context, dmlite_fopen, "/file", O_RDONLY, dict); /* Read */ TEST_ASSERT_EQUAL(4, dmlite_fread(file, buffer, 4)); buffer[5] = '\0'; TEST_ASSERT_STR_EQUAL("abcd", buffer); TEST_ASSERT_EQUAL(4, dmlite_fread(file, buffer, 4)); buffer[5] = '\0'; TEST_ASSERT_STR_EQUAL("efgh", buffer); /* Seek and read */ TEST_ASSERT_EQUAL(0, dmlite_fseek(file, 10, SEEK_SET)); TEST_ASSERT_EQUAL(4, dmlite_fread(file, buffer, 4)); buffer[5] = '\0'; TEST_ASSERT_STR_EQUAL("klmn", buffer); TEST_ASSERT_EQUAL(14, dmlite_ftell(file)); TEST_ASSERT_EQUAL(0, dmlite_feof(file)); /* Free */ TEST_ASSERT_EQUAL(0, dmlite_fclose(file)); dmlite_any_dict_free(dict); }
void testPut(dmlite_context* context) { char buffer[64]; SECTION("PUT"); /* Mock returns always one single location with one token */ dmlite_location* loc; TEST_CONTEXT_CALL_PTR(loc, context, dmlite_put, "/file"); TEST_ASSERT_EQUAL(1, loc->nchunks); TEST_ASSERT_STR_EQUAL("host1.cern.ch", loc->chunks[0].host); TEST_ASSERT_STR_EQUAL("/storage/chunk01", loc->chunks[0].path); TEST_ASSERT_EQUAL(0, loc->chunks[0].offset); TEST_ASSERT_EQUAL(0, loc->chunks[0].size); dmlite_any* extra = dmlite_any_dict_get(loc->chunks[0].extra, "token"); dmlite_any_to_string(extra, buffer, sizeof(buffer)); TEST_ASSERT_STR_EQUAL("987654321", buffer); dmlite_any_free(extra); dmlite_location_free(context, loc); /* A donewriting without token will fail */ dmlite_any_dict* dict = dmlite_any_dict_new(); TEST_ASSERT_EQUAL(DM_FORBIDDEN, dmlite_donewriting(context, "/storage/chunk01", dict)); /* With token */ dmlite_any* token = dmlite_any_new_string("987654321"); dmlite_any_dict_insert(dict, "token", token); TEST_CONTEXT_CALL(context, dmlite_donewriting, "/storage/chunk01", dict); dmlite_any_free(token); dmlite_any_dict_free(dict); }
/** * Open a stream. Used for PUT * @param resource The resource to open * @param mode The mode (basically, trucate or random, which we don't support) * @param stream Where to put the created structure * @return NULL on success */ static dav_error *dav_ns_open_stream(const dav_resource *resource, dav_stream_mode mode, dav_stream **stream) { dav_resource_private *info; unsigned has_range; const char *range, *length; int e; info = resource->info; /* Must be writable (if we are here, they want to write) */ if (!(info->d_conf->flags & DAV_NS_WRITE)) return dav_shared_new_error(info->request, NULL, HTTP_FORBIDDEN, "Configured as read-only endpoint (%s)", resource->uri); /* If content-length is 0, call create instead of put! */ length = apr_table_get(info->request->headers_in, "content-length"); if (length != NULL) { size_t clen = atol(length); if (clen == 0) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, info->request, "PUT with content-length 0. Creating ns entry."); if (dmlite_create(info->ctx, info->sfn, 0644) != 0) return dav_shared_new_error(info->request, info->ctx, 0, "Could not create empty file %s", info->sfn); *stream = (dav_stream*)calloc(1, sizeof(dav_stream)); return NULL; } } /* NS alone doesn't support PUTs with content! */ if (info->s_conf->type == DAV_NS_NODE_LFC) return dav_shared_new_error(info->request, NULL, HTTP_NOT_IMPLEMENTED, "LFC does not support PUTs"); /* Range header? */ range = apr_table_get(info->request->headers_in, "content-range"); has_range = (range != NULL); if (has_range) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, info->request, "Range: %s", range); } /* If token not set, call dm_put and see where do we have to go */ if (info->space_token != NULL) { dmlite_any* any = dmlite_any_new_string(info->space_token); e = dmlite_set(info->ctx, "SpaceToken", any); dmlite_any_free(any); if (e) return dav_shared_new_error(info->request, info->ctx, 0, "Could not set the space token %s", info->space_token); } dmlite_location *location; location = dmlite_put(info->ctx, info->sfn); switch (dmlite_errno(info->ctx)) { case 0: break; case DM_INVALID_VALUE: return dav_shared_new_error(info->request, info->ctx, HTTP_BAD_REQUEST, "Can not get the space token %s", info->space_token); default: return dav_shared_new_error(info->request, info->ctx, 0, "Can not put %s", info->sfn); } /* Redirect */ info->redirect = apr_psprintf(resource->pool, "%s://%s%s%s", info->d_conf->redir_scheme, location->chunks[0].host, location->chunks[0].path, dav_shared_build_extra(resource->pool, location->chunks[0].extra)); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, info->request, "PUT request to be done in %s", info->redirect); apr_table_set(info->request->headers_out, "Location", info->redirect); dmlite_location_free(info->ctx, location); /* Standard says 301/302, but some clients will retry in that case with a GET. * 307 is unambiguous */ return dav_new_error(resource->pool, HTTP_TEMPORARY_REDIRECT, 0, info->redirect); }