1/* 2* Copyright (c) 2004, Bull S.A.. All rights reserved. 3* Created by: Sebastien Decugis 4 5* This program is free software; you can redistribute it and/or modify it 6* under the terms of version 2 of the GNU General Public License as 7* published by the Free Software Foundation. 8* 9* This program is distributed in the hope that it would be useful, but 10* WITHOUT ANY WARRANTY; without even the implied warranty of 11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12* 13* You should have received a copy of the GNU General Public License along 14* with this program; if not, write the Free Software Foundation, Inc., 59 15* Temple Place - Suite 330, Boston MA 02111-1307, USA. 16 17 18* This sample test aims to check the following assertion: 19* 20* The new process is a copy of the original one -- with few exceptions. 21 22* The steps are: 23* -> set up some data in process memory space 24* -> create a new process 25* -> check in this new process that the memory space was copied. 26* 27* We check that: 28* -> a structure object is copied. 29* -> a malloc'ed memory block is copied and can be freed in child. 30* -> the environment is copied 31* -> signal handlers are copied 32 33 34* The test fails if a difference is detected. 35 36*/ 37 38 39/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 40#define _POSIX_C_SOURCE 200112L 41 42/* We can use XSI features in case it is allowed */ 43#ifndef WITHOUT_XOPEN 44#define _XOPEN_SOURCE 600 45#endif 46 47/********************************************************************************************/ 48/****************************** standard includes *****************************************/ 49/********************************************************************************************/ 50#include <pthread.h> 51 #include <stdarg.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 57#include <sys/wait.h> 58 #include <errno.h> 59 60#include <signal.h> 61 62/********************************************************************************************/ 63/****************************** Test framework *****************************************/ 64/********************************************************************************************/ 65#include "testfrmw.h" 66 #include "testfrmw.c" 67/* This header is responsible for defining the following macros: 68 * UNRESOLVED(ret, descr); 69 * where descr is a description of the error and ret is an int (error code for example) 70 * FAILED(descr); 71 * where descr is a short text saying why the test has failed. 72 * PASSED(); 73 * No parameter. 74 * 75 * Both three macros shall terminate the calling process. 76 * The testcase shall not terminate in any other maneer. 77 * 78 * The other file defines the functions 79 * void output_init() 80 * void output(char * string, ...) 81 * 82 * Those may be used to output information. 83 */ 84 85/********************************************************************************************/ 86/********************************** Configuration ******************************************/ 87/********************************************************************************************/ 88#ifndef VERBOSE 89#define VERBOSE 1 90#endif 91 92 93/********************************************************************************************/ 94/*********************************** Test case *****************************************/ 95/********************************************************************************************/ 96 97void handler( int sig ) 98{ 99 /* this won't be used */ 100 output( "Sig %d received\n", sig ); 101 102 return ; 103} 104 105 106/* The main test function. */ 107int main( int argc, char * argv[] ) 108{ 109 int ret, status; 110 pid_t child, ctl; 111 112 /* structure for structure test */ 113 114 struct _thestruct 115 { 116 char one ; 117 short two; 118 int three; 119 void * four; 120 } 121 122 mystruct = {1, 2, 3, ( void * ) 4}; 123 124 /* pointer for malloc'ed memory */ 125 void * malloced; 126 127 /* Structure for signal handler test */ 128 129 struct sigaction sa_ori, sa_child; 130 131 /* Initialize output */ 132 output_init(); 133 134 /* Initialize the memory pointer */ 135 malloced = ( void * ) malloc( sysconf( _SC_PAGESIZE ) ); 136 137 if ( malloced == NULL ) 138 { 139 UNRESOLVED( errno, "Unable to alloc memory" ); 140 } 141 142 *( double * ) malloced = 2.3; 143 144 /* Initialize an environment variable */ 145 ret = setenv( "OPTS_FORK_TC", "2-1.c", 1 ); 146 147 if ( ret != 0 ) 148 { 149 UNRESOLVED( errno, "Failed to set the environment variable" ); 150 } 151 152 /* Initialize the signal handler */ 153 sa_ori.sa_handler = handler; 154 155 ret = sigemptyset( &sa_ori.sa_mask ); 156 157 if ( ret != 0 ) 158 { 159 UNRESOLVED( errno, "sigemptyset failed" ); 160 } 161 162 ret = sigaddset( &sa_ori.sa_mask, SIGUSR2 ); 163 164 if ( ret != 0 ) 165 { 166 UNRESOLVED( errno, "sigaddset failed" ); 167 } 168 169 sa_ori.sa_flags = SA_NOCLDSTOP; 170 ret = sigaction( SIGUSR1, &sa_ori, NULL ); 171 172 if ( ret != 0 ) 173 { 174 UNRESOLVED( errno, "Failed to set the signal handler" ); 175 } 176 177 /* Create the child */ 178 child = fork(); 179 180 if ( child == ( pid_t ) - 1 ) 181 { 182 UNRESOLVED( errno, "Failed to fork" ); 183 } 184 185 /* child */ 186 if ( child == ( pid_t ) 0 ) 187 { 188 /* Check the struct was copied */ 189 190 if ( ( mystruct.one != 1 ) || ( mystruct.two != 2 ) || ( mystruct.three != 3 ) || ( mystruct.four != ( void * ) 4 ) ) 191 { 192 FAILED( "The struct data was not copied to the child process" ); 193 } 194 195 /* Check the malloc'ed memory is copied */ 196 if ( *( double * ) malloced != 2.3 ) 197 { 198 FAILED( "Malloc'd block not copied in child process" ); 199 } 200 201 /* Free the memory -- this should suceed */ 202 free( malloced ); 203 204 /* Check the env variable */ 205 if ( strncmp( "2-1.c", getenv( "OPTS_FORK_TC" ), 6 ) != 0 ) 206 { 207 FAILED( "The environment is not copied to the child" ); 208 } 209 210 /* Check the signal handler stuff */ 211 ret = sigaction( SIGUSR1, NULL, &sa_child ); 212 213 if ( ret != 0 ) 214 { 215 UNRESOLVED( errno, "Failed to read sigaction information in child" ); 216 } 217 218 if ( sa_child.sa_handler != handler ) 219 { 220 FAILED( "The child signal handler function is different from the parent's" ); 221 } 222 223 ret = sigismember( &sa_child.sa_mask, SIGUSR2 ); 224 225 if ( ret == 0 ) 226 { 227 FAILED( "The child signal handler mask is different from the parent's" ); 228 } 229 230 if ( ret != 1 ) 231 { 232 UNRESOLVED( errno, "Unexpected return code from sigismember" ); 233 } 234 235 if ( ( ( sa_child.sa_flags & SA_NOCLDSTOP ) != SA_NOCLDSTOP ) 236#ifndef WITHOUT_XOPEN 237 || ( ( sa_child.sa_flags & SA_ONSTACK ) != 0 ) 238 || ( ( sa_child.sa_flags & SA_RESETHAND ) != 0 ) 239 || ( ( sa_child.sa_flags & SA_RESTART ) != 0 ) 240 || ( ( sa_child.sa_flags & SA_SIGINFO ) != 0 ) 241 || ( ( sa_child.sa_flags & SA_NOCLDWAIT ) != 0 ) 242 || ( ( sa_child.sa_flags & SA_NODEFER ) != 0 ) 243#endif 244 ) 245 { 246 FAILED( "The sigaction flags are different in the child" ); 247 } 248 249 /* The child stops here */ 250 exit( PTS_PASS ); 251 } 252 253 /* Parent joins the child */ 254 ctl = waitpid( child, &status, 0 ); 255 256 if ( ctl != child ) 257 { 258 UNRESOLVED( errno, "Waitpid returned the wrong PID" ); 259 } 260 261 if ( !WIFEXITED( status ) ) 262 { 263 UNRESOLVED( status, "Child exited abnormally" ); 264 } 265 266 if ( WEXITSTATUS( status ) == PTS_PASS ) 267 { 268 269 /* Test passed */ 270#if VERBOSE > 0 271 output( "Test passed\n" ); 272#endif 273 274 PASSED; 275 } 276 277 if ( WEXITSTATUS( status ) == PTS_FAIL ) 278 { 279 280 /* Test failed */ 281 FAILED( "Test failed in child\n" ); 282 } 283 284 /* Otherwise we've an unexpected return code */ 285 UNRESOLVED( WEXITSTATUS( status ), "Child returned an unexpected error code" ); 286} 287 288 289