1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
48 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
56 #define INCL_DOSFILEMGR
62 static int _debug_on = 0;
72 #define DPRINTF(arg) if (_debug_on) printf arg
80 #define BUF_DATA_SIZE 256 * 120
82 #define BUF_DATA_SIZE 256 * 1024
85 #define NUM_RDWR_THREADS 10
86 #define NUM_DIRTEST_THREADS 4
87 #define CHUNK_SIZE 512
89 typedef struct buffer {
90 char data[BUF_DATA_SIZE];
93 typedef struct File_Rdwr_Param {
102 char *TEST_DIR = "prdir";
104 char *TEST_DIR = "C:\\temp\\prdir";
106 char *FILE_NAME = "pr_testfile";
107 char *HIDDEN_FILE_NAME = "hidden_pr_testfile";
110 char *TEST_DIR = "c:\\data\\testfile_dir";
112 char *TEST_DIR = "/tmp/testfile_dir";
114 char *FILE_NAME = "pr_testfile";
115 char *HIDDEN_FILE_NAME = ".hidden_pr_testfile";
117 buffer *in_buf, *out_buf;
118 char pathname[256], renamename[256];
120 WCHAR wPathname[256];
122 #define TMPDIR_LEN 64
123 char testdir[TMPDIR_LEN];
124 static PRInt32 PR_CALLBACK DirTest(void *argunused);
125 PRInt32 dirtest_failed = 0;
127 PRThread* create_new_thread(PRThreadType type,
128 void (*start)(void *arg),
130 PRThreadPriority priority,
133 PRUint32 stackSize, PRInt32 index)
135 PRInt32 native_thread = 0;
137 PR_ASSERT(state == PR_UNJOINABLE_THREAD);
139 #if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32) || defined(XP_OS2)
143 scope = (PR_LOCAL_THREAD);
146 scope = (PR_GLOBAL_THREAD);
149 scope = (PR_GLOBAL_BOUND_THREAD);
155 PR_ASSERT(!"Invalid scope");
159 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
161 if (!pthread_create(&tid, NULL, start, arg))
162 return((PRThread *) tid);
165 #elif defined(XP_OS2)
168 tid = (TID)_beginthread((void(* _Optlink)(void*))start,
171 printf("_beginthread failed. errno %d\n", errno);
175 return((PRThread *) tid);
180 thandle = (HANDLE) _beginthreadex(
183 (unsigned (__stdcall *)(void *))start,
187 return((PRThread *) thandle);
190 return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
193 return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
197 static void PR_CALLBACK File_Write(void *arg)
200 File_Rdwr_Param *fp = (File_Rdwr_Param *) arg;
204 setbuf(stdout, NULL);
210 fd_file = PR_Open(name, PR_RDWR | PR_CREATE_FILE, 0777);
211 if (fd_file == NULL) {
212 printf("testfile failed to create/open file %s\n",name);
215 if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) {
216 printf("testfile failed to seek in file %s\n",name);
219 if ((PR_Write(fd_file, buf, len)) < 0) {
220 printf("testfile failed to write to file %s\n",name);
223 DPRINTF(("Write out_buf[0] = 0x%x\n",(*((int *) buf))));
227 PR_EnterMonitor(mon);
233 static void PR_CALLBACK File_Read(void *arg)
236 File_Rdwr_Param *fp = (File_Rdwr_Param *) arg;
240 setbuf(stdout, NULL);
246 fd_file = PR_Open(name, PR_RDONLY, 0);
247 if (fd_file == NULL) {
248 printf("testfile failed to open file %s\n",name);
251 if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) {
252 printf("testfile failed to seek in file %s\n",name);
255 if ((PR_Read(fd_file, buf, len)) < 0) {
256 printf("testfile failed to read to file %s\n",name);
259 DPRINTF(("Read in_buf[0] = 0x%x\n",(*((int *) buf))));
263 PR_EnterMonitor(mon);
270 static PRInt32 Misc_File_Tests(char *pathname)
274 PRFileInfo file_info, file_info1;
277 setbuf(stdout, NULL);
279 * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
282 fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
284 if (fd_file == NULL) {
285 printf("testfile failed to create/open file %s\n",pathname);
288 if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
289 printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
293 if (PR_Access(pathname, PR_ACCESS_EXISTS) != 0) {
294 printf("testfile PR_Access failed on file %s\n",pathname);
298 if (PR_Access(pathname, PR_ACCESS_WRITE_OK) != 0) {
299 printf("testfile PR_Access failed on file %s\n",pathname);
303 if (PR_Access(pathname, PR_ACCESS_READ_OK) != 0) {
304 printf("testfile PR_Access failed on file %s\n",pathname);
310 if (PR_GetFileInfo(pathname, &file_info) < 0) {
311 printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
315 if (file_info.type != PR_FILE_FILE) {
317 "testfile: Error - PR_GetFileInfo returned incorrect type for file %s\n",
322 if (file_info.size != 0) {
324 "testfile PR_GetFileInfo returned incorrect size (%d should be 0) for file %s\n",
325 file_info.size, pathname);
329 file_info1 = file_info;
331 len = PR_Available(fd_file);
333 printf("testfile PR_Available failed on file %s\n",pathname);
336 } else if (len != 0) {
338 "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
343 if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
344 printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
347 if (LL_NE(file_info.creationTime , file_info1.creationTime)) {
349 "testfile PR_GetFileInfo returned incorrect status-change time: %s\n",
351 printf("ft = %lld, ft1 = %lld\n",file_info.creationTime,
352 file_info1.creationTime);
356 len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
358 printf("testfile failed to write to file %s\n",pathname);
362 if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
363 printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
366 if (file_info.size != CHUNK_SIZE) {
368 "testfile PR_GetFileInfo returned incorrect size (%d should be %d) for file %s\n",
369 file_info.size, CHUNK_SIZE, pathname);
373 if (LL_CMP(file_info.modifyTime, < , file_info1.modifyTime)) {
375 "testfile PR_GetFileInfo returned incorrect modify time: %s\n",
377 printf("ft = %lld, ft1 = %lld\n",file_info.modifyTime,
378 file_info1.modifyTime);
383 len = PR_Available(fd_file);
385 printf("testfile PR_Available failed on file %s\n",pathname);
388 } else if (len != 0) {
390 "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
396 PR_Seek(fd_file, 0, PR_SEEK_SET);
397 len = PR_Available(fd_file);
399 printf("testfile PR_Available failed on file %s\n",pathname);
402 } else if (len != CHUNK_SIZE) {
404 "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
411 strcpy(tmpname,pathname);
412 strcat(tmpname,".RENAMED");
413 if (PR_FAILURE == PR_Rename(pathname, tmpname)) {
414 printf("testfile failed to rename file %s\n",pathname);
419 fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
420 len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
422 if (PR_SUCCESS == PR_Rename(pathname, tmpname)) {
423 printf("testfile renamed to existing file %s\n",pathname);
426 if ((PR_Delete(tmpname)) < 0) {
427 printf("testfile failed to unlink file %s\n",tmpname);
432 if ((PR_Delete(pathname)) < 0) {
433 printf("testfile failed to unlink file %s\n",pathname);
440 static PRInt32 PR_CALLBACK FileTest(void)
443 int i, offset, len, rv = 0;
445 PRThreadScope scope = PR_GLOBAL_THREAD;
446 File_Rdwr_Param *fparamp;
451 if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
452 printf("testfile failed to create dir %s\n",TEST_DIR);
455 fd_dir = PR_OpenDir(TEST_DIR);
456 if (fd_dir == NULL) {
457 printf("testfile failed to open dir %s\n",TEST_DIR);
464 strcat(pathname, TEST_DIR);
465 strcat(pathname, "/");
466 strcat(pathname, FILE_NAME);
468 in_buf = PR_NEW(buffer);
469 if (in_buf == NULL) {
471 "testfile failed to alloc buffer struct\n");
475 out_buf = PR_NEW(buffer);
476 if (out_buf == NULL) {
478 "testfile failed to alloc buffer struct\n");
484 * Start a bunch of writer threads
488 PR_EnterMonitor(mon);
489 for (i = 0; i < NUM_RDWR_THREADS; i++) {
490 fparamp = PR_NEW(File_Rdwr_Param);
491 if (fparamp == NULL) {
493 "testfile failed to alloc File_Rdwr_Param struct\n");
497 fparamp->pathname = pathname;
498 fparamp->buf = out_buf->data + offset;
499 fparamp->offset = offset;
501 memset(fparamp->buf, i, len);
503 t = create_new_thread(PR_USER_THREAD,
504 File_Write, (void *)fparamp,
507 PR_UNJOINABLE_THREAD,
512 /* Wait for writer threads to exit */
513 while (thread_count) {
514 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
520 * Start a bunch of reader threads
524 PR_EnterMonitor(mon);
525 for (i = 0; i < NUM_RDWR_THREADS; i++) {
526 fparamp = PR_NEW(File_Rdwr_Param);
527 if (fparamp == NULL) {
529 "testfile failed to alloc File_Rdwr_Param struct\n");
533 fparamp->pathname = pathname;
534 fparamp->buf = in_buf->data + offset;
535 fparamp->offset = offset;
538 t = create_new_thread(PR_USER_THREAD,
539 File_Read, (void *)fparamp,
542 PR_UNJOINABLE_THREAD,
545 if ((offset + len) > BUF_DATA_SIZE)
550 /* Wait for reader threads to exit */
551 while (thread_count) {
552 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
556 if (memcmp(in_buf->data, out_buf->data, offset) != 0) {
557 printf("File Test failed: file data corrupted\n");
562 if ((PR_Delete(pathname)) < 0) {
563 printf("testfile failed to unlink file %s\n",pathname);
569 * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
571 if (Misc_File_Tests(pathname) < 0) {
576 if ((PR_RmDir(TEST_DIR)) < 0) {
577 printf("testfile failed to rmdir %s\n", TEST_DIR);
588 static PRInt32 RunDirTest(void)
593 struct dirtest_arg thrarg;
595 mon = PR_NewMonitor();
597 printf("RunDirTest: Error - failed to create monitor\n");
603 for (i = 0; i < NUM_DIRTEST_THREADS; i++) {
606 t = create_new_thread(PR_USER_THREAD,
610 PR_UNJOINABLE_THREAD,
613 printf("RunDirTest: Error - failed to create thread\n");
617 PR_EnterMonitor(mon);
619 PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
623 PR_DestroyMonitor(mon);
627 static PRInt32 PR_CALLBACK DirTest(void *arg)
629 struct dirtest_arg *tinfo = (struct dirtest_arg *) arg;
634 PRDirEntry *dirEntry;
636 PRInt32 num_files = 0;
637 #if defined(XP_PC) && defined(WIN32)
641 #define FILES_IN_DIR 20
646 DPRINTF(("Creating test dir %s\n",TEST_DIR));
647 if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
649 "testfile failed to create dir %s [%d, %d]\n",
650 TEST_DIR, PR_GetError(), PR_GetOSError());
653 fd_dir = PR_OpenDir(TEST_DIR);
654 if (fd_dir == NULL) {
656 "testfile failed to open dirctory %s [%d, %d]\n",
657 TEST_DIR, PR_GetError(), PR_GetOSError());
661 strcpy(pathname, TEST_DIR);
662 strcat(pathname, "/");
663 strcat(pathname, FILE_NAME);
664 path_len = strlen(pathname);
666 for (i = 0; i < FILES_IN_DIR; i++) {
668 sprintf(pathname + path_len,"%d%s",i,"");
670 DPRINTF(("Creating test file %s\n",pathname));
672 fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
674 if (fd_file == NULL) {
676 "testfile failed to create/open file %s [%d, %d]\n",
677 pathname, PR_GetError(), PR_GetOSError());
682 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
684 * Create a hidden file - a platform-dependent operation
686 strcpy(pathname, TEST_DIR);
687 strcat(pathname, "/");
688 strcat(pathname, HIDDEN_FILE_NAME);
689 #if defined(XP_UNIX) || defined(XP_BEOS)
690 DPRINTF(("Creating hidden test file %s\n",pathname));
691 fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
693 if (fd_file == NULL) {
695 "testfile failed to create/open hidden file %s [%d, %d]\n",
696 pathname, PR_GetError(), PR_GetOSError());
703 DPRINTF(("Creating hidden test file %s\n",pathname));
704 MultiByteToWideChar(CP_ACP, 0, pathname, -1, wPathname, 256);
705 hfile = CreateFile(wPathname, GENERIC_READ,
706 FILE_SHARE_READ|FILE_SHARE_WRITE,
709 FILE_ATTRIBUTE_HIDDEN,
711 if (hfile == INVALID_HANDLE_VALUE) {
712 printf("testfile failed to create/open hidden file %s [0, %d]\n",
713 pathname, GetLastError());
718 #elif defined(XP_PC) && defined(WIN32)
719 DPRINTF(("Creating hidden test file %s\n",pathname));
720 hfile = CreateFile(pathname, GENERIC_READ,
721 FILE_SHARE_READ|FILE_SHARE_WRITE,
724 FILE_ATTRIBUTE_HIDDEN,
726 if (hfile == INVALID_HANDLE_VALUE) {
727 printf("testfile failed to create/open hidden file %s [0, %d]\n",
728 pathname, GetLastError());
734 DPRINTF(("Creating hidden test file %s\n",pathname));
735 fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, (int)FILE_HIDDEN);
737 if (fd_file == NULL) {
738 printf("testfile failed to create/open hidden file %s [%d, %d]\n",
739 pathname, PR_GetError(), PR_GetOSError());
745 #endif /* XP_UNIX || (XP_PC && WIN32) */
748 if (PR_FAILURE == PR_CloseDir(fd_dir))
751 "testfile failed to close dirctory %s [%d, %d]\n",
752 TEST_DIR, PR_GetError(), PR_GetOSError());
755 fd_dir = PR_OpenDir(TEST_DIR);
756 if (fd_dir == NULL) {
758 "testfile failed to reopen dirctory %s [%d, %d]\n",
759 TEST_DIR, PR_GetError(), PR_GetOSError());
764 * List all files, including hidden files
766 DPRINTF(("Listing all files in directory %s\n",TEST_DIR));
767 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
768 num_files = FILES_IN_DIR + 1;
770 num_files = FILES_IN_DIR;
772 while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_BOTH)) != NULL) {
774 strcpy(pathname, TEST_DIR);
775 strcat(pathname, "/");
776 strcat(pathname, dirEntry->name);
777 DPRINTF(("\t%s\n",dirEntry->name));
779 if ((PR_GetFileInfo(pathname, &info)) < 0) {
781 "testfile failed to GetFileInfo file %s [%d, %d]\n",
782 pathname, PR_GetError(), PR_GetOSError());
786 if (info.type != PR_FILE_FILE) {
788 "testfile incorrect fileinfo for file %s [%d, %d]\n",
789 pathname, PR_GetError(), PR_GetOSError());
796 "testfile failed to find all files in directory %s [%d, %d]\n",
797 TEST_DIR, PR_GetError(), PR_GetOSError());
803 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
806 * List all files, except hidden files
809 fd_dir = PR_OpenDir(TEST_DIR);
810 if (fd_dir == NULL) {
812 "testfile failed to reopen dirctory %s [%d, %d]\n",
813 TEST_DIR, PR_GetError(), PR_GetOSError());
817 DPRINTF(("Listing non-hidden files in directory %s\n",TEST_DIR));
818 while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_HIDDEN)) != NULL) {
819 DPRINTF(("\t%s\n",dirEntry->name));
820 if (!strcmp(HIDDEN_FILE_NAME, dirEntry->name)) {
821 printf("testfile found hidden file %s\n", pathname);
829 strcpy(pathname, TEST_DIR);
830 strcat(pathname, "/");
831 strcat(pathname, HIDDEN_FILE_NAME);
832 if (PR_FAILURE == PR_Delete(pathname)) {
834 "testfile failed to delete hidden file %s [%d, %d]\n",
835 pathname, PR_GetError(), PR_GetOSError());
840 #endif /* XP_UNIX || (XP_PC && WIN32) */
842 strcpy(renamename, TEST_DIR);
843 strcat(renamename, ".RENAMED");
844 if (PR_FAILURE == PR_Rename(TEST_DIR, renamename)) {
846 "testfile failed to rename directory %s [%d, %d]\n",
847 TEST_DIR, PR_GetError(), PR_GetOSError());
851 if (PR_FAILURE == PR_MkDir(TEST_DIR, 0777)) {
853 "testfile failed to recreate dir %s [%d, %d]\n",
854 TEST_DIR, PR_GetError(), PR_GetOSError());
857 if (PR_SUCCESS == PR_Rename(renamename, TEST_DIR)) {
859 "testfile renamed directory to existing name %s\n",
864 if (PR_FAILURE == PR_RmDir(TEST_DIR)) {
866 "testfile failed to rmdir %s [%d, %d]\n",
867 TEST_DIR, PR_GetError(), PR_GetOSError());
871 if (PR_FAILURE == PR_Rename(renamename, TEST_DIR)) {
873 "testfile failed to rename directory %s [%d, %d]\n",
874 renamename, PR_GetError(), PR_GetOSError());
877 fd_dir = PR_OpenDir(TEST_DIR);
878 if (fd_dir == NULL) {
880 "testfile failed to reopen directory %s [%d, %d]\n",
881 TEST_DIR, PR_GetError(), PR_GetOSError());
885 strcpy(pathname, TEST_DIR);
886 strcat(pathname, "/");
887 strcat(pathname, FILE_NAME);
888 path_len = strlen(pathname);
890 for (i = 0; i < FILES_IN_DIR; i++) {
892 sprintf(pathname + path_len,"%d%s",i,"");
894 if (PR_FAILURE == PR_Delete(pathname)) {
896 "testfile failed to delete file %s [%d, %d]\n",
897 pathname, PR_GetError(), PR_GetOSError());
904 if (PR_FAILURE == PR_RmDir(TEST_DIR)) {
906 "testfile failed to rmdir %s [%d, %d]\n",
907 TEST_DIR, PR_GetError(), PR_GetOSError());
910 PR_EnterMonitor(tinfo->mon);
912 PR_Notify(tinfo->mon);
913 PR_ExitMonitor(tinfo->mon);
917 /************************************************************************/
920 * Test file and directory NSPR APIs
923 int main(int argc, char **argv)
928 #if defined(XP_UNIX) || defined(XP_OS2)
933 #if defined(XP_UNIX) || defined(XP_OS2)
934 while ((opt = getopt(argc, argv, "d")) != EOF) {
944 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
947 mon = PR_NewMonitor();
949 printf("testfile: PR_NewMonitor failed\n");
956 WCHAR tdir[TMPDIR_LEN];
957 len = GetTempPath(TMPDIR_LEN, tdir);
958 if ((len > 0) && (len < (TMPDIR_LEN - 6))) {
960 * enough space for prdir
962 WideCharToMultiByte(CP_ACP, 0, tdir, -1, testdir, TMPDIR_LEN, 0, 0);
966 len = GetTempPath(TMPDIR_LEN, testdir);
969 if ((len > 0) && (len < (TMPDIR_LEN - 6))) {
971 * enough space for prdir
973 strcpy((testdir + len),"prdir");
975 printf("TEST_DIR = %s\n",TEST_DIR);
979 if (FileTest() < 0) {
980 printf("File Test failed\n");
983 printf("File Test passed\n");
984 if ((RunDirTest() < 0) || dirtest_failed) {
985 printf("Dir Test failed\n");
988 printf("Dir Test passed\n");
990 PR_DestroyMonitor(mon);