1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
16 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
24 #define INCL_DOSFILEMGR
30 static int _debug_on
= 0;
40 #define DPRINTF(arg) if (_debug_on) printf arg
48 #define BUF_DATA_SIZE 256 * 120
50 #define BUF_DATA_SIZE 256 * 1024
53 #define NUM_RDWR_THREADS 10
54 #define NUM_DIRTEST_THREADS 4
55 #define CHUNK_SIZE 512
57 typedef struct buffer
{
58 char data
[BUF_DATA_SIZE
];
61 typedef struct File_Rdwr_Param
{
70 char *TEST_DIR
= "prdir";
72 char *TEST_DIR
= "C:\\temp\\prdir";
74 char *FILE_NAME
= "pr_testfile";
75 char *HIDDEN_FILE_NAME
= "hidden_pr_testfile";
78 char *TEST_DIR
= "c:\\data\\testfile_dir";
80 char *TEST_DIR
= "/tmp/testfile_dir";
82 char *FILE_NAME
= "pr_testfile";
83 char *HIDDEN_FILE_NAME
= ".hidden_pr_testfile";
85 buffer
*in_buf
, *out_buf
;
86 char pathname
[256], renamename
[256];
91 char testdir
[TMPDIR_LEN
];
92 static PRInt32 PR_CALLBACK
DirTest(void *argunused
);
93 PRInt32 dirtest_failed
= 0;
95 PRThread
* create_new_thread(PRThreadType type
,
96 void (*start
)(void *arg
),
98 PRThreadPriority priority
,
101 PRUint32 stackSize
, PRInt32 index
)
103 PRInt32 native_thread
= 0;
105 PR_ASSERT(state
== PR_UNJOINABLE_THREAD
);
107 #if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32) || defined(XP_OS2)
111 scope
= (PR_LOCAL_THREAD
);
114 scope
= (PR_GLOBAL_THREAD
);
117 scope
= (PR_GLOBAL_BOUND_THREAD
);
123 PR_ASSERT(!"Invalid scope");
127 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
129 if (!pthread_create(&tid
, NULL
, start
, arg
))
130 return((PRThread
*) tid
);
133 #elif defined(XP_OS2)
136 tid
= (TID
)_beginthread((void(* _Optlink
)(void*))start
,
139 printf("_beginthread failed. errno %d\n", errno
);
143 return((PRThread
*) tid
);
148 thandle
= (HANDLE
) _beginthreadex(
151 (unsigned (__stdcall
*)(void *))start
,
155 return((PRThread
*) thandle
);
158 return(PR_CreateThread(type
,start
,arg
,priority
,scope
,state
,stackSize
));
161 return(PR_CreateThread(type
,start
,arg
,priority
,scope
,state
,stackSize
));
165 static void PR_CALLBACK
File_Write(void *arg
)
168 File_Rdwr_Param
*fp
= (File_Rdwr_Param
*) arg
;
172 setbuf(stdout
, NULL
);
178 fd_file
= PR_Open(name
, PR_RDWR
| PR_CREATE_FILE
, 0777);
179 if (fd_file
== NULL
) {
180 printf("testfile failed to create/open file %s\n",name
);
183 if (PR_Seek(fd_file
, offset
, PR_SEEK_SET
) < 0) {
184 printf("testfile failed to seek in file %s\n",name
);
187 if ((PR_Write(fd_file
, buf
, len
)) < 0) {
188 printf("testfile failed to write to file %s\n",name
);
191 DPRINTF(("Write out_buf[0] = 0x%x\n",(*((int *) buf
))));
195 PR_EnterMonitor(mon
);
201 static void PR_CALLBACK
File_Read(void *arg
)
204 File_Rdwr_Param
*fp
= (File_Rdwr_Param
*) arg
;
208 setbuf(stdout
, NULL
);
214 fd_file
= PR_Open(name
, PR_RDONLY
, 0);
215 if (fd_file
== NULL
) {
216 printf("testfile failed to open file %s\n",name
);
219 if (PR_Seek(fd_file
, offset
, PR_SEEK_SET
) < 0) {
220 printf("testfile failed to seek in file %s\n",name
);
223 if ((PR_Read(fd_file
, buf
, len
)) < 0) {
224 printf("testfile failed to read to file %s\n",name
);
227 DPRINTF(("Read in_buf[0] = 0x%x\n",(*((int *) buf
))));
231 PR_EnterMonitor(mon
);
238 static PRInt32
Misc_File_Tests(char *pathname
)
242 PRFileInfo file_info
, file_info1
;
245 setbuf(stdout
, NULL
);
247 * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
250 fd_file
= PR_Open(pathname
, PR_RDWR
| PR_CREATE_FILE
, 0777);
252 if (fd_file
== NULL
) {
253 printf("testfile failed to create/open file %s\n",pathname
);
256 if (PR_GetOpenFileInfo(fd_file
, &file_info
) < 0) {
257 printf("testfile PR_GetFileInfo failed on file %s\n",pathname
);
261 if (PR_Access(pathname
, PR_ACCESS_EXISTS
) != 0) {
262 printf("testfile PR_Access failed on file %s\n",pathname
);
266 if (PR_Access(pathname
, PR_ACCESS_WRITE_OK
) != 0) {
267 printf("testfile PR_Access failed on file %s\n",pathname
);
271 if (PR_Access(pathname
, PR_ACCESS_READ_OK
) != 0) {
272 printf("testfile PR_Access failed on file %s\n",pathname
);
278 if (PR_GetFileInfo(pathname
, &file_info
) < 0) {
279 printf("testfile PR_GetFileInfo failed on file %s\n",pathname
);
283 if (file_info
.type
!= PR_FILE_FILE
) {
285 "testfile: Error - PR_GetFileInfo returned incorrect type for file %s\n",
290 if (file_info
.size
!= 0) {
292 "testfile PR_GetFileInfo returned incorrect size (%d should be 0) for file %s\n",
293 file_info
.size
, pathname
);
297 file_info1
= file_info
;
299 len
= PR_Available(fd_file
);
301 printf("testfile PR_Available failed on file %s\n",pathname
);
304 } else if (len
!= 0) {
306 "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
311 if (PR_GetOpenFileInfo(fd_file
, &file_info
) < 0) {
312 printf("testfile PR_GetFileInfo failed on file %s\n",pathname
);
315 if (LL_NE(file_info
.creationTime
, file_info1
.creationTime
)) {
317 "testfile PR_GetFileInfo returned incorrect status-change time: %s\n",
319 printf("ft = %lld, ft1 = %lld\n",file_info
.creationTime
,
320 file_info1
.creationTime
);
324 len
= PR_Write(fd_file
, out_buf
->data
, CHUNK_SIZE
);
326 printf("testfile failed to write to file %s\n",pathname
);
330 if (PR_GetOpenFileInfo(fd_file
, &file_info
) < 0) {
331 printf("testfile PR_GetFileInfo failed on file %s\n",pathname
);
334 if (file_info
.size
!= CHUNK_SIZE
) {
336 "testfile PR_GetFileInfo returned incorrect size (%d should be %d) for file %s\n",
337 file_info
.size
, CHUNK_SIZE
, pathname
);
341 if (LL_CMP(file_info
.modifyTime
, < , file_info1
.modifyTime
)) {
343 "testfile PR_GetFileInfo returned incorrect modify time: %s\n",
345 printf("ft = %lld, ft1 = %lld\n",file_info
.modifyTime
,
346 file_info1
.modifyTime
);
351 len
= PR_Available(fd_file
);
353 printf("testfile PR_Available failed on file %s\n",pathname
);
356 } else if (len
!= 0) {
358 "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
364 PR_Seek(fd_file
, 0, PR_SEEK_SET
);
365 len
= PR_Available(fd_file
);
367 printf("testfile PR_Available failed on file %s\n",pathname
);
370 } else if (len
!= CHUNK_SIZE
) {
372 "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
379 strcpy(tmpname
,pathname
);
380 strcat(tmpname
,".RENAMED");
381 if (PR_FAILURE
== PR_Rename(pathname
, tmpname
)) {
382 printf("testfile failed to rename file %s\n",pathname
);
387 fd_file
= PR_Open(pathname
, PR_RDWR
| PR_CREATE_FILE
, 0777);
388 len
= PR_Write(fd_file
, out_buf
->data
, CHUNK_SIZE
);
390 if (PR_SUCCESS
== PR_Rename(pathname
, tmpname
)) {
391 printf("testfile renamed to existing file %s\n",pathname
);
394 if ((PR_Delete(tmpname
)) < 0) {
395 printf("testfile failed to unlink file %s\n",tmpname
);
400 if ((PR_Delete(pathname
)) < 0) {
401 printf("testfile failed to unlink file %s\n",pathname
);
408 static PRInt32 PR_CALLBACK
FileTest(void)
411 int i
, offset
, len
, rv
= 0;
413 PRThreadScope scope
= PR_GLOBAL_THREAD
;
414 File_Rdwr_Param
*fparamp
;
419 if ((PR_MkDir(TEST_DIR
, 0777)) < 0) {
420 printf("testfile failed to create dir %s\n",TEST_DIR
);
423 fd_dir
= PR_OpenDir(TEST_DIR
);
424 if (fd_dir
== NULL
) {
425 printf("testfile failed to open dir %s\n",TEST_DIR
);
432 strcat(pathname
, TEST_DIR
);
433 strcat(pathname
, "/");
434 strcat(pathname
, FILE_NAME
);
436 in_buf
= PR_NEW(buffer
);
437 if (in_buf
== NULL
) {
439 "testfile failed to alloc buffer struct\n");
443 out_buf
= PR_NEW(buffer
);
444 if (out_buf
== NULL
) {
446 "testfile failed to alloc buffer struct\n");
452 * Start a bunch of writer threads
456 PR_EnterMonitor(mon
);
457 for (i
= 0; i
< NUM_RDWR_THREADS
; i
++) {
458 fparamp
= PR_NEW(File_Rdwr_Param
);
459 if (fparamp
== NULL
) {
461 "testfile failed to alloc File_Rdwr_Param struct\n");
465 fparamp
->pathname
= pathname
;
466 fparamp
->buf
= out_buf
->data
+ offset
;
467 fparamp
->offset
= offset
;
469 memset(fparamp
->buf
, i
, len
);
471 t
= create_new_thread(PR_USER_THREAD
,
472 File_Write
, (void *)fparamp
,
475 PR_UNJOINABLE_THREAD
,
480 /* Wait for writer threads to exit */
481 while (thread_count
) {
482 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
488 * Start a bunch of reader threads
492 PR_EnterMonitor(mon
);
493 for (i
= 0; i
< NUM_RDWR_THREADS
; i
++) {
494 fparamp
= PR_NEW(File_Rdwr_Param
);
495 if (fparamp
== NULL
) {
497 "testfile failed to alloc File_Rdwr_Param struct\n");
501 fparamp
->pathname
= pathname
;
502 fparamp
->buf
= in_buf
->data
+ offset
;
503 fparamp
->offset
= offset
;
506 t
= create_new_thread(PR_USER_THREAD
,
507 File_Read
, (void *)fparamp
,
510 PR_UNJOINABLE_THREAD
,
513 if ((offset
+ len
) > BUF_DATA_SIZE
)
518 /* Wait for reader threads to exit */
519 while (thread_count
) {
520 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
524 if (memcmp(in_buf
->data
, out_buf
->data
, offset
) != 0) {
525 printf("File Test failed: file data corrupted\n");
530 if ((PR_Delete(pathname
)) < 0) {
531 printf("testfile failed to unlink file %s\n",pathname
);
537 * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
539 if (Misc_File_Tests(pathname
) < 0) {
544 if ((PR_RmDir(TEST_DIR
)) < 0) {
545 printf("testfile failed to rmdir %s\n", TEST_DIR
);
556 static PRInt32
RunDirTest(void)
561 struct dirtest_arg thrarg
;
563 mon
= PR_NewMonitor();
565 printf("RunDirTest: Error - failed to create monitor\n");
571 for (i
= 0; i
< NUM_DIRTEST_THREADS
; i
++) {
574 t
= create_new_thread(PR_USER_THREAD
,
578 PR_UNJOINABLE_THREAD
,
581 printf("RunDirTest: Error - failed to create thread\n");
585 PR_EnterMonitor(mon
);
587 PR_Wait(mon
, PR_INTERVAL_NO_TIMEOUT
);
591 PR_DestroyMonitor(mon
);
595 static PRInt32 PR_CALLBACK
DirTest(void *arg
)
597 struct dirtest_arg
*tinfo
= (struct dirtest_arg
*) arg
;
602 PRDirEntry
*dirEntry
;
604 PRInt32 num_files
= 0;
605 #if defined(XP_PC) && defined(WIN32)
609 #define FILES_IN_DIR 20
614 DPRINTF(("Creating test dir %s\n",TEST_DIR
));
615 if ((PR_MkDir(TEST_DIR
, 0777)) < 0) {
617 "testfile failed to create dir %s [%d, %d]\n",
618 TEST_DIR
, PR_GetError(), PR_GetOSError());
621 fd_dir
= PR_OpenDir(TEST_DIR
);
622 if (fd_dir
== NULL
) {
624 "testfile failed to open dirctory %s [%d, %d]\n",
625 TEST_DIR
, PR_GetError(), PR_GetOSError());
629 strcpy(pathname
, TEST_DIR
);
630 strcat(pathname
, "/");
631 strcat(pathname
, FILE_NAME
);
632 path_len
= strlen(pathname
);
634 for (i
= 0; i
< FILES_IN_DIR
; i
++) {
636 sprintf(pathname
+ path_len
,"%d%s",i
,"");
638 DPRINTF(("Creating test file %s\n",pathname
));
640 fd_file
= PR_Open(pathname
, PR_RDWR
| PR_CREATE_FILE
, 0777);
642 if (fd_file
== NULL
) {
644 "testfile failed to create/open file %s [%d, %d]\n",
645 pathname
, PR_GetError(), PR_GetOSError());
650 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
652 * Create a hidden file - a platform-dependent operation
654 strcpy(pathname
, TEST_DIR
);
655 strcat(pathname
, "/");
656 strcat(pathname
, HIDDEN_FILE_NAME
);
657 #if defined(XP_UNIX) || defined(XP_BEOS)
658 DPRINTF(("Creating hidden test file %s\n",pathname
));
659 fd_file
= PR_Open(pathname
, PR_RDWR
| PR_CREATE_FILE
, 0777);
661 if (fd_file
== NULL
) {
663 "testfile failed to create/open hidden file %s [%d, %d]\n",
664 pathname
, PR_GetError(), PR_GetOSError());
671 DPRINTF(("Creating hidden test file %s\n",pathname
));
672 MultiByteToWideChar(CP_ACP
, 0, pathname
, -1, wPathname
, 256);
673 hfile
= CreateFile(wPathname
, GENERIC_READ
,
674 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
677 FILE_ATTRIBUTE_HIDDEN
,
679 if (hfile
== INVALID_HANDLE_VALUE
) {
680 printf("testfile failed to create/open hidden file %s [0, %d]\n",
681 pathname
, GetLastError());
686 #elif defined(XP_PC) && defined(WIN32)
687 DPRINTF(("Creating hidden test file %s\n",pathname
));
688 hfile
= CreateFile(pathname
, GENERIC_READ
,
689 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
692 FILE_ATTRIBUTE_HIDDEN
,
694 if (hfile
== INVALID_HANDLE_VALUE
) {
695 printf("testfile failed to create/open hidden file %s [0, %d]\n",
696 pathname
, GetLastError());
702 DPRINTF(("Creating hidden test file %s\n",pathname
));
703 fd_file
= PR_Open(pathname
, PR_RDWR
| PR_CREATE_FILE
, (int)FILE_HIDDEN
);
705 if (fd_file
== NULL
) {
706 printf("testfile failed to create/open hidden file %s [%d, %d]\n",
707 pathname
, PR_GetError(), PR_GetOSError());
713 #endif /* XP_UNIX || (XP_PC && WIN32) */
716 if (PR_FAILURE
== PR_CloseDir(fd_dir
))
719 "testfile failed to close dirctory %s [%d, %d]\n",
720 TEST_DIR
, PR_GetError(), PR_GetOSError());
723 fd_dir
= PR_OpenDir(TEST_DIR
);
724 if (fd_dir
== NULL
) {
726 "testfile failed to reopen dirctory %s [%d, %d]\n",
727 TEST_DIR
, PR_GetError(), PR_GetOSError());
732 * List all files, including hidden files
734 DPRINTF(("Listing all files in directory %s\n",TEST_DIR
));
735 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
736 num_files
= FILES_IN_DIR
+ 1;
738 num_files
= FILES_IN_DIR
;
740 while ((dirEntry
= PR_ReadDir(fd_dir
, PR_SKIP_BOTH
)) != NULL
) {
742 strcpy(pathname
, TEST_DIR
);
743 strcat(pathname
, "/");
744 strcat(pathname
, dirEntry
->name
);
745 DPRINTF(("\t%s\n",dirEntry
->name
));
747 if ((PR_GetFileInfo(pathname
, &info
)) < 0) {
749 "testfile failed to GetFileInfo file %s [%d, %d]\n",
750 pathname
, PR_GetError(), PR_GetOSError());
754 if (info
.type
!= PR_FILE_FILE
) {
756 "testfile incorrect fileinfo for file %s [%d, %d]\n",
757 pathname
, PR_GetError(), PR_GetOSError());
764 "testfile failed to find all files in directory %s [%d, %d]\n",
765 TEST_DIR
, PR_GetError(), PR_GetOSError());
771 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
774 * List all files, except hidden files
777 fd_dir
= PR_OpenDir(TEST_DIR
);
778 if (fd_dir
== NULL
) {
780 "testfile failed to reopen dirctory %s [%d, %d]\n",
781 TEST_DIR
, PR_GetError(), PR_GetOSError());
785 DPRINTF(("Listing non-hidden files in directory %s\n",TEST_DIR
));
786 while ((dirEntry
= PR_ReadDir(fd_dir
, PR_SKIP_HIDDEN
)) != NULL
) {
787 DPRINTF(("\t%s\n",dirEntry
->name
));
788 if (!strcmp(HIDDEN_FILE_NAME
, dirEntry
->name
)) {
789 printf("testfile found hidden file %s\n", pathname
);
797 strcpy(pathname
, TEST_DIR
);
798 strcat(pathname
, "/");
799 strcat(pathname
, HIDDEN_FILE_NAME
);
800 if (PR_FAILURE
== PR_Delete(pathname
)) {
802 "testfile failed to delete hidden file %s [%d, %d]\n",
803 pathname
, PR_GetError(), PR_GetOSError());
808 #endif /* XP_UNIX || (XP_PC && WIN32) */
810 strcpy(renamename
, TEST_DIR
);
811 strcat(renamename
, ".RENAMED");
812 if (PR_FAILURE
== PR_Rename(TEST_DIR
, renamename
)) {
814 "testfile failed to rename directory %s [%d, %d]\n",
815 TEST_DIR
, PR_GetError(), PR_GetOSError());
819 if (PR_FAILURE
== PR_MkDir(TEST_DIR
, 0777)) {
821 "testfile failed to recreate dir %s [%d, %d]\n",
822 TEST_DIR
, PR_GetError(), PR_GetOSError());
825 if (PR_SUCCESS
== PR_Rename(renamename
, TEST_DIR
)) {
827 "testfile renamed directory to existing name %s\n",
832 if (PR_FAILURE
== PR_RmDir(TEST_DIR
)) {
834 "testfile failed to rmdir %s [%d, %d]\n",
835 TEST_DIR
, PR_GetError(), PR_GetOSError());
839 if (PR_FAILURE
== PR_Rename(renamename
, TEST_DIR
)) {
841 "testfile failed to rename directory %s [%d, %d]\n",
842 renamename
, PR_GetError(), PR_GetOSError());
845 fd_dir
= PR_OpenDir(TEST_DIR
);
846 if (fd_dir
== NULL
) {
848 "testfile failed to reopen directory %s [%d, %d]\n",
849 TEST_DIR
, PR_GetError(), PR_GetOSError());
853 strcpy(pathname
, TEST_DIR
);
854 strcat(pathname
, "/");
855 strcat(pathname
, FILE_NAME
);
856 path_len
= strlen(pathname
);
858 for (i
= 0; i
< FILES_IN_DIR
; i
++) {
860 sprintf(pathname
+ path_len
,"%d%s",i
,"");
862 if (PR_FAILURE
== PR_Delete(pathname
)) {
864 "testfile failed to delete file %s [%d, %d]\n",
865 pathname
, PR_GetError(), PR_GetOSError());
872 if (PR_FAILURE
== PR_RmDir(TEST_DIR
)) {
874 "testfile failed to rmdir %s [%d, %d]\n",
875 TEST_DIR
, PR_GetError(), PR_GetOSError());
878 PR_EnterMonitor(tinfo
->mon
);
880 PR_Notify(tinfo
->mon
);
881 PR_ExitMonitor(tinfo
->mon
);
885 /************************************************************************/
888 * Test file and directory NSPR APIs
891 int main(int argc
, char **argv
)
896 #if defined(XP_UNIX) || defined(XP_OS2)
901 #if defined(XP_UNIX) || defined(XP_OS2)
902 while ((opt
= getopt(argc
, argv
, "d")) != EOF
) {
912 PR_Init(PR_USER_THREAD
, PR_PRIORITY_NORMAL
, 0);
915 mon
= PR_NewMonitor();
917 printf("testfile: PR_NewMonitor failed\n");
924 WCHAR tdir
[TMPDIR_LEN
];
925 len
= GetTempPath(TMPDIR_LEN
, tdir
);
926 if ((len
> 0) && (len
< (TMPDIR_LEN
- 6))) {
928 * enough space for prdir
930 WideCharToMultiByte(CP_ACP
, 0, tdir
, -1, testdir
, TMPDIR_LEN
, 0, 0);
934 len
= GetTempPath(TMPDIR_LEN
, testdir
);
937 if ((len
> 0) && (len
< (TMPDIR_LEN
- 6))) {
939 * enough space for prdir
941 strcpy((testdir
+ len
),"prdir");
943 printf("TEST_DIR = %s\n",TEST_DIR
);
947 if (FileTest() < 0) {
948 printf("File Test failed\n");
951 printf("File Test passed\n");
952 if ((RunDirTest() < 0) || dirtest_failed
) {
953 printf("Dir Test failed\n");
956 printf("Dir Test passed\n");
958 PR_DestroyMonitor(mon
);