nsprpub/pr/tests/bigfile.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/tests/bigfile.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,291 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "prio.h"
    1.10 +#include "prmem.h"
    1.11 +#include "prprf.h"
    1.12 +#include "prinit.h"
    1.13 +#include "prerror.h"
    1.14 +#include "prthread.h"
    1.15 +
    1.16 +#include "plerror.h"
    1.17 +#include "plgetopt.h"
    1.18 +
    1.19 +#define DEFAULT_COUNT 10
    1.20 +#define DEFAULT_FILESIZE 1
    1.21 +#define BUFFER_SIZE 1000000
    1.22 +
    1.23 +typedef enum {v_silent, v_whisper, v_shout} Verbosity;
    1.24 +static void Verbose(Verbosity, const char*, const char*, PRIntn);
    1.25 +
    1.26 +#define VERBOSE(_l, _m) Verbose(_l, _m, __FILE__, __LINE__)
    1.27 +
    1.28 +static PRIntn test_result = 2;
    1.29 +static PRFileDesc *output = NULL;
    1.30 +static PRIntn verbose = v_silent;
    1.31 +static PRIntn filesize = DEFAULT_FILESIZE;
    1.32 +
    1.33 +static PRIntn Usage(void)
    1.34 +{
    1.35 +    PR_fprintf(output, "Bigfile test usage:\n");
    1.36 +    PR_fprintf(output, ">bigfile [-G] [-d] [-v[*v]] [-s <n>] <filename>\n");
    1.37 +    PR_fprintf(output, "\td\tdebug mode (equivalent to -vvv)\t(false)\n");
    1.38 +    PR_fprintf(output, "\tv\tAdditional levels of output\t(none)\n");
    1.39 +    PR_fprintf(output, "\tk\tKeep data file after exit\t(false)\n");
    1.40 +    PR_fprintf(output, "\ts <n>\tFile size in megabytes\t\t(1 megabyte)\n");
    1.41 +    PR_fprintf(output, "\t<filename>\tName of test file\t(none)\n");
    1.42 +    return 2;  /* nothing happened */
    1.43 +}  /* Usage */
    1.44 +
    1.45 +static PRStatus DeleteIfFound(const char *filename)
    1.46 +{
    1.47 +    PRStatus rv;
    1.48 +    VERBOSE(v_shout, "Checking for existing file");
    1.49 +    rv = PR_Access(filename, PR_ACCESS_WRITE_OK);
    1.50 +    if (PR_SUCCESS == rv)
    1.51 +    {
    1.52 +        VERBOSE(v_shout, "Deleting existing file");
    1.53 +        rv = PR_Delete(filename);
    1.54 +        if (PR_FAILURE == rv) VERBOSE(v_shout, "Cannot delete big file");
    1.55 +    }
    1.56 +    else if (PR_FILE_NOT_FOUND_ERROR !=  PR_GetError())
    1.57 +        VERBOSE(v_shout, "Cannot access big file");
    1.58 +    else rv = PR_SUCCESS;
    1.59 +    return rv;
    1.60 +}  /* DeleteIfFound */
    1.61 +
    1.62 +static PRIntn Error(const char *msg, const char *filename)
    1.63 +{
    1.64 +    PRInt32 error = PR_GetError();
    1.65 +    if (NULL != msg)
    1.66 +    {
    1.67 +        if (0 == error) PR_fprintf(output, msg);
    1.68 +        else PL_FPrintError(output, msg);
    1.69 +    }
    1.70 +    (void)DeleteIfFound(filename);
    1.71 +    if (v_shout == verbose) PR_Abort();
    1.72 +    return 1;
    1.73 +}  /* Error */
    1.74 +
    1.75 +static void Verbose(
    1.76 +    Verbosity level, const char *msg, const char *file, PRIntn line)
    1.77 +{
    1.78 +    if (level <= verbose)
    1.79 +        PR_fprintf(output, "[%s : %d]: %s\n", file, line, msg);
    1.80 +}  /* Verbose */
    1.81 +
    1.82 +static void PrintInfo(PRFileInfo64 *info, const char *filename)
    1.83 +{
    1.84 +    PRExplodedTime tm;
    1.85 +    char ctime[40], mtime[40];
    1.86 +    static const char *types[] = {"FILE", "DIRECTORY", "OTHER"};
    1.87 +    PR_fprintf(
    1.88 +        output, "[%s : %d]: File info for %s\n",
    1.89 +        __FILE__, __LINE__, filename);
    1.90 +    PR_fprintf(
    1.91 +        output, "    type: %s, size: %llu bytes,\n",
    1.92 +        types[info->type - 1], info->size);
    1.93 +
    1.94 +    PR_ExplodeTime(info->creationTime, PR_GMTParameters, &tm);
    1.95 +    (void)PR_FormatTime(ctime, sizeof(ctime), "%c GMT", &tm);
    1.96 +    PR_ExplodeTime(info->modifyTime, PR_GMTParameters, &tm);
    1.97 +    (void)PR_FormatTime(mtime, sizeof(mtime), "%c GMT", &tm);
    1.98 +
    1.99 +    PR_fprintf(
   1.100 +        output, "    creation: %s,\n    modify: %s\n", ctime, mtime);
   1.101 +}  /* PrintInfo */
   1.102 +
   1.103 +int main(int argc, char **argv)
   1.104 +{
   1.105 +    PRStatus rv;
   1.106 +    char *buffer;
   1.107 +    PLOptStatus os;
   1.108 +    PRInt32 loop, bytes;
   1.109 +    PRFileInfo small_info;
   1.110 +    PRFileInfo64 big_info;
   1.111 +    PRBool keep = PR_FALSE;
   1.112 +    PRFileDesc *file = NULL;
   1.113 +    const char *filename = NULL;
   1.114 +    PRIntn count = DEFAULT_COUNT;
   1.115 +    PRInt64 filesize64, big_answer, big_size, one_meg, zero_meg, big_fragment;
   1.116 +    PRInt64 sevenFox = LL_INIT(0,0x7fffffff);
   1.117 +
   1.118 +    PLOptState *opt = PL_CreateOptState(argc, argv, "dtvhs:");
   1.119 +
   1.120 +    output = PR_GetSpecialFD(PR_StandardError);
   1.121 +    PR_STDIO_INIT();
   1.122 +
   1.123 +    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   1.124 +    {
   1.125 +        if (PL_OPT_BAD == os) continue;
   1.126 +        switch (opt->option)
   1.127 +        {
   1.128 +        case 0:
   1.129 +            filename = opt->value;
   1.130 +            break;
   1.131 +        case 'd':  /* debug mode */
   1.132 +            verbose = v_shout;
   1.133 +            break;
   1.134 +        case 'k':  /* keep file */
   1.135 +            keep = PR_TRUE;
   1.136 +            break;
   1.137 +        case 'v':  /* verbosity */
   1.138 +            if (v_shout > verbose) verbose += 1;
   1.139 +            break;
   1.140 +        case 'c':  /* loop counter */
   1.141 +            count = atoi(opt->value);
   1.142 +            break;
   1.143 +        case 's':  /* filesize */
   1.144 +            filesize = atoi(opt->value);
   1.145 +            break;
   1.146 +        case 'h':  /* confused */
   1.147 +        default:
   1.148 +            return Usage();
   1.149 +        }
   1.150 +    }
   1.151 +    PL_DestroyOptState(opt);
   1.152 +
   1.153 +    if (0 == count) count = DEFAULT_COUNT;
   1.154 +    if (0 == filesize) filesize = DEFAULT_FILESIZE;
   1.155 +    if (NULL == filename)
   1.156 +    {
   1.157 +#ifdef SYMBIAN
   1.158 +#define FILE_NAME "c:\\data\\bigfile.dat"
   1.159 +#else
   1.160 +#define FILE_NAME "bigfile.dat"
   1.161 +#endif
   1.162 +        if (DEFAULT_FILESIZE != filesize) return Usage();
   1.163 +        else filename = FILE_NAME;
   1.164 +    }
   1.165 +
   1.166 +    if (PR_FAILURE == DeleteIfFound(filename)) return 1;
   1.167 +
   1.168 +    test_result = 0;
   1.169 +
   1.170 +    LL_I2L(zero_meg, 0);
   1.171 +    LL_I2L(one_meg, 1000000);
   1.172 +    LL_I2L(filesize64, filesize);
   1.173 +    buffer = (char*)PR_MALLOC(BUFFER_SIZE);
   1.174 +    LL_I2L(big_fragment, BUFFER_SIZE);
   1.175 +    LL_MUL(filesize64, filesize64, one_meg); 
   1.176 +
   1.177 +    for (loop = 0; loop < BUFFER_SIZE; ++loop) buffer[loop] = (char)loop;
   1.178 +
   1.179 +    VERBOSE(v_whisper, "Creating big file");
   1.180 +    file = PR_Open(filename, PR_CREATE_FILE | PR_WRONLY, 0666);
   1.181 +    if (NULL == file) return Error("PR_Open()", filename);
   1.182 +    
   1.183 +    VERBOSE(v_whisper, "Testing available space in empty file");
   1.184 +    big_answer = file->methods->available64(file);
   1.185 +    if (!LL_IS_ZERO(big_answer)) return Error("empty available64()", filename);
   1.186 +
   1.187 +	LL_SUB(big_size, filesize64, one_meg);
   1.188 +    VERBOSE(v_whisper, "Creating sparse big file by seeking to end");
   1.189 +	big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET);
   1.190 +    if (!LL_EQ(big_answer, big_size)) return Error("seek", filename);
   1.191 +
   1.192 +    VERBOSE(v_whisper, "Writing block at end of sparse file");
   1.193 +	bytes = file->methods->write(file, buffer, BUFFER_SIZE);
   1.194 +    if (bytes != BUFFER_SIZE) return Error("write", filename);
   1.195 +
   1.196 +    VERBOSE(v_whisper, "Testing available space at end of sparse file");
   1.197 +    big_answer = file->methods->available64(file);
   1.198 +    if (!LL_IS_ZERO(big_answer)) return Error("eof available64()", filename);
   1.199 +
   1.200 +    VERBOSE(v_whisper, "Getting big info on sparse big file");
   1.201 +    rv = file->methods->fileInfo64(file, &big_info);
   1.202 +    if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
   1.203 +    if (v_shout <= verbose) PrintInfo(&big_info, filename);
   1.204 +
   1.205 +    VERBOSE(v_whisper, "Getting small info on sparse big file");
   1.206 +    rv = file->methods->fileInfo(file, &small_info);
   1.207 +    if (LL_CMP(sevenFox, <, filesize64) && (PR_SUCCESS == rv))
   1.208 +    {
   1.209 +        VERBOSE(v_whisper, "Should have failed and didn't");
   1.210 +        return Error("fileInfo()", filename);
   1.211 +    }
   1.212 +    else if (LL_CMP(sevenFox, >, filesize64) && (PR_FAILURE == rv))
   1.213 +    {
   1.214 +        VERBOSE(v_whisper, "Should have succeeded and didn't");
   1.215 +        return Error("fileInfo()", filename);
   1.216 +    }
   1.217 +
   1.218 +    VERBOSE(v_whisper, "Rewinding big file");
   1.219 +    big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
   1.220 +    if (!LL_IS_ZERO(big_answer)) return Error("rewind seek64()", filename);
   1.221 +
   1.222 +    VERBOSE(v_whisper, "Establishing available space in rewound file");
   1.223 +    big_answer = file->methods->available64(file);
   1.224 +    if (LL_NE(filesize64, big_answer))
   1.225 +        return Error("bof available64()", filename);
   1.226 +
   1.227 +    VERBOSE(v_whisper, "Closing big file");
   1.228 +    rv = file->methods->close(file);
   1.229 +    if (PR_FAILURE == rv) return Error("close()", filename);
   1.230 +
   1.231 +    VERBOSE(v_whisper, "Reopening big file");
   1.232 +    file = PR_Open(filename, PR_RDWR, 0666);
   1.233 +    if (NULL == file) return Error("open failed", filename);
   1.234 +
   1.235 +    VERBOSE(v_whisper, "Checking available data in reopened file");
   1.236 +    big_answer = file->methods->available64(file);
   1.237 +    if (LL_NE(filesize64, big_answer))
   1.238 +        return Error("reopened available64()", filename);
   1.239 +
   1.240 +    big_answer = zero_meg;
   1.241 +    VERBOSE(v_whisper, "Rewriting every byte of big file data");
   1.242 +    do
   1.243 +    {
   1.244 +        bytes = file->methods->write(file, buffer, BUFFER_SIZE);
   1.245 +        if (bytes != BUFFER_SIZE)
   1.246 +            return Error("write", filename);
   1.247 +        LL_ADD(big_answer, big_answer, big_fragment);
   1.248 +    } while (LL_CMP(big_answer, <, filesize64));
   1.249 +
   1.250 +    VERBOSE(v_whisper, "Checking position at eof");
   1.251 +    big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_CUR);
   1.252 +    if (LL_NE(big_answer, filesize64))
   1.253 +        return Error("file size error", filename);
   1.254 +
   1.255 +    VERBOSE(v_whisper, "Testing available space at eof");
   1.256 +    big_answer = file->methods->available64(file);
   1.257 +    if (!LL_IS_ZERO(big_answer))
   1.258 +        return Error("eof available64()", filename);
   1.259 +
   1.260 +    VERBOSE(v_whisper, "Rewinding full file");
   1.261 +    big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
   1.262 +    if (!LL_IS_ZERO(big_answer)) return Error("bof seek64()", filename);
   1.263 +
   1.264 +    VERBOSE(v_whisper, "Testing available space in rewound file");
   1.265 +    big_answer = file->methods->available64(file);
   1.266 +    if (LL_NE(big_answer, filesize64)) return Error("bof available64()", filename);
   1.267 +
   1.268 +    VERBOSE(v_whisper, "Seeking to end of big file");
   1.269 +    big_answer = file->methods->seek64(file, filesize64, PR_SEEK_SET);
   1.270 +    if (LL_NE(big_answer, filesize64)) return Error("eof seek64()", filename);
   1.271 +
   1.272 +    VERBOSE(v_whisper, "Getting info on big file while it's open");
   1.273 +    rv = file->methods->fileInfo64(file, &big_info);
   1.274 +    if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
   1.275 +    if (v_shout <= verbose) PrintInfo(&big_info, filename);
   1.276 +
   1.277 +    VERBOSE(v_whisper, "Closing big file");
   1.278 +    rv = file->methods->close(file);
   1.279 +    if (PR_FAILURE == rv) return Error("close()", filename);
   1.280 +
   1.281 +    VERBOSE(v_whisper, "Getting info on big file after it's closed");
   1.282 +    rv = PR_GetFileInfo64(filename, &big_info);
   1.283 +    if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
   1.284 +    if (v_shout <= verbose) PrintInfo(&big_info, filename);
   1.285 +
   1.286 +    VERBOSE(v_whisper, "Deleting big file");
   1.287 +    rv = PR_Delete(filename);
   1.288 +    if (PR_FAILURE == rv) return Error("PR_Delete()", filename);
   1.289 +
   1.290 +    PR_DELETE(buffer);
   1.291 +    return test_result;
   1.292 +} /* main */
   1.293 +
   1.294 +/* bigfile.c */

mercurial