Method for testing a message-driven operating system

Abstract: A simulation system to simulate the execution of a computer program. The computer program is developed for invoking operating system functions of a first operating system. Each operating system function performs a behavior in accordance with passed parameters. The simulation system generates a log during the execution of the computer program under control of the first operating system. The log includes an indication of each invocation of an operating system function by the computer program and an indication of each parameter passed to the operating system function by the computer program and the current time. The logged execution is then simulated by the simulation system on a second operating system. The simulation system invokes an operating system function of the second operating system to perform a behavior similar to the behavior performed by each logged invocation of the operating system function of the first operating system in accordance with the passed parameters. Comparison of the functionality, reliability, and performance of the two systems are thereby enabled.

Description: Technical Field This invention relates generally to a computer method and system for simulating the execution of a computer program. Background of the Invention Computer operating systems are very complex computer programs. When developing or modifying an operating system, it is critical that the operating system be thoroughly tested. The testing of an operating system typically involves several testing phases. First, the programmer who writes a program for the operating system performs "unit testing." This unit testing ensures that the program functions as intended by the programmer. Second, the programmers who developed various programs perform integration testing. This integration testing ensures that the various programs function together correctly. Third, the developer of the operating system performs alpha testing of the operating system. During alpha testing, application programs are executed with the operating system and any anomalies are logged for later correction. Finally, end users of the operating system perform beta testing. The beta testing ensures that the operating system will function correctly in the end user's environment. The testing of an operating system can be very time consuming and expensive. Furthermore, it is virtually impossible to ensure that the operating system is error free. Generally, operating system developers concentrate on ensuring that the operating system will function correctly with "standard applications." A standard application is an application program that a typical user of the operating system may use. By testing with these standard applications, a developer can help ensure the operating system will function correctly in most typical situations. Certain operating systems are referred to as message-driven operating systems. One such operating system is Windows 3.1, developed by Microsoft Corporation. A description of Windows 3.1 is provided in the Software Development Kit for Windows 3.1, which is available from Microsoft Corporation. The Windows operating system provides a windowing environment for applications that support a graphical user interface (GUI). Figure 1 is a block diagram illustrating the messaging architecture of a typical message-driven operating system. An application program 110 contains a main procedure 111 and a window procedure 112. When the application program 110 is executed under the control of the operating system, control is passed to the main procedure 111. The main procedure 111 typically creates and displays a window and then enters a message loop 113. When executing the message loop, the application program 110 waits to receive a message from the operating system 120 indicating an external event (e.g., key down). The messages received by the message loop are referred to as posted messages. When a message is received, the application program 110 processes the message by requesting the operating system 120 to dispatch the message to the appropriate window procedure. The application program 110 includes a window procedure 112 for each window that is displayed on display monitor 130. A window procedure is invoked by the operating system when a message is dispatched to that window or when the operating system sends (discussed below) a message to that window. The window procedure decodes the message and processes the message accordingly. For example, a message dispatched to the window procedure may indicate that a character has been depressed on the keyboard when the window has the focus. A window that has the focus receives all keyboard and mouse inputs. The operating system 120 provides various functions to application programs that provide services to the application programs. These functions may include: RegisterClass, CreateWindow, ShowWindow, GetMessage, DispatchMessage, and DefWindowProc. These functions are collectively referred to as the application programming interface (API) provided by the operating system, and each function may be individually referred to as an API. During execution of the application program 110, the application program invokes the various functions provided by the operating system. These functions are typically stored in a dynamic link library. When the application program is initially loaded into memory, it dynamically links to each of the functions it uses. As shown by the main procedure 111, the application program 110 initially invokes the function RegisterClass to register a window class with the operating system. Each window class has an associated window procedure for processing messages that are sent to a window. The operating system maintains a window class table 122, which correlates a window class with its window procedure. When a window class is registered, the operating system stores the address of the window procedure in the window class table 122. When a message is to be sent to a window, the operating system invokes the associated window procedure passing it various parameters including the type of the message. A window procedure is a type of a callback routine. A callback routine is a routine that is part of the application program but is invoked directly by the operating system. The application program provides the operating system with the address of a callback routine that is developed to perform application-specific processing. The operating system then invokes the callback routine to perform the processing. The operating system also maintains a message queue 121 for the application program 110. The message queue 121 contains messages that are posted to the application program. Each invocation of the function GetMessage in the message loop 113 retrieves a message from the message queue 121. The posted messages in the message queue typically correspond to external events such as mouse movement. When the operating system detects mouse movement over the window on the display monitor 130, the operating system posts a message to the message queue for the application program. The application program during the message loop retrieves each posted message and invokes the function DispatchMessage to process the message. The function DispatchMessage determines which window procedure the message is directed to and sends the message to that window by invoking its window procedure. Not all messages are posted, dispatched, and then sent to the window procedure. The operating system sometimes sends messages directly to a window procedure, without first posting the message to the message queue. For example, when a window is first created, the operating system may send a create message (WM_CREATE) to the window procedure for that window. This message allows the window procedure to perform initialization of the window. DE-A-41 18 454 describes a technique for testing a program. A journal module records user inputs. The recorded user inputs are then replayed, that is each recorded input is sent to a program to be tested. A safe data module records the output of the program to be tested, a comparation module compares the recorded output to master data and a graphical review of the differences is generated. Thus, the reference suggests a journal mechanism which provides the basic capability of recording events in a journal file representative of use actions taken to initiate and execute certain tasks, to test the computer system and/or software operating on the computer system. The journal file is subsequently replayed, whereby each event recorded is read from the journal file and input to the window system in the sequence recorded. It is the object of the present invention to provide a method and system for testing an operating system using application programs that have not yet been converted to execute under the operating system. This object is solved by the subject matter of claims 1 and 16. In a preferred embodiment, a computer system simulates an execution of a client program that requests services of a first server program. During execution of the client program, the requests for services are logged. A simulation program receives the logged requests for services and requests a second server program to simulate the behavior of the requested service. In another preferred embodiment, a simulation system simulates the execution of a computer program. The computer program is developed for invoking operating system functions of a prior operating system. Each operating system function performs a behavior in accordance with passed parameters. The simulation system generates a log during the execution of the computer program under control of the prior operating system. The log includes an indication of each invocation of an operating system function by the computer program and an indication of each parameter passed to the operating system function by the computer program. The logged execution is then simulated on a new operating system. The simulation system invokes an operating system function of the new operating system to perform a behavior similar to the behavior performed by the logged invocation of the operating system function of the prior operating system in accordance with the passed parameters. Brief Description of the Drawings Figure 1 is a block diagram illustrating the messaging architecture of a typical message-driven operating system. Figures 2A, 2B, and 2C are block diagrams illustrating the recording of the interaction and the simulation of an application program. Figure 3 is a block diagram illustrating a preferred architecture of the logger. Figure 4 is a flow diagram of a sample substitute function. Figure 5 is a flow diagram of a routine to log a function invocation. Figure 6 is a flow diagram illustrating the recording of a typical integer parameter that is passed by value. Figure 7 is a flow diagram illustrating a routine that records a parameter that is passed as a pointer to a buffer. Figure 8 is a flow diagram of the processing of a parameter that points to a callback routine. Figure 9 is a flow diagram of a typical substitute callback routine. Figure 10A is an overview diagram illustrating the synthetic GUI application. Figure 10B is a flow diagram of the synthetic GUI application program. Figure 11 is a flow diagram of the routine GenerateSentMessageFile. Figure 12 is a flow diagram of the routine GeneratePostedMessageFile. Figure 13 is a flow diagram of the SGAEngine routine. Figure 14 is a flow diagram of the routine FindMessageInSentMessageFile. Figure 15 is a flow diagram of the routine SimulatePostedMessage. Figure 16 is a flow diagram of a routine that simulates the posting of the WM_KEYDOWN message. Figure 17 is a flow diagram of a routine that simulates a WM_MOUSEMOVE message. Figure 18 is a flow diagram of a thunk window procedure. Figure 19 is a flow diagram of the routine ThunkRegisterClass. Figure 20 is a flow diagram of the routine ThunkCreateWindow. Figure 21 is a flow diagram of the procedure ThunkDestroyWindow. Figure 22 is a flow diagram of a template thunk function. Figure 23 is a block diagram illustrating an alternate embodiment of the present invention. Detailed Description of the Invention The present invention provides a method and system for simulating the execution of an application program. In a preferred embodiment, the simulation system first records the interaction between the application program and an existing operating system (an old operating system) during an execution of the application program. The simulation system then takes this recorded interaction and simulates the interaction with a new operating system. To record the interaction, the simulation system executes the application program under the control of the old operating system. During execution of the application program, a logger portion of the simulation system records each invocation of an operating system function by the application program and records each invocation of a callback routine by the operating system. The logger also records all the parameters passed to each function and all the parameters returned by each callback routine. The logger also preferably records all parameters returned by each function and all parameters passed to each callback routine. The logger records this information in a log file. The simulation system then simulates the execution of the application program on a new operating system. A synthetic GUI application (SGA) of the simulation system inputs the log file and invokes the functions of the new operating system to effect the behavior of the logged function invocations. The SGA also provides thunk callback routines for the new operating system to invoke. The thunk callback routines simulate the behavior of the real callback routines of the application program. The SGA also simulates the occurrence of the real events (e.g., key down) that occurred during the execution of the application program. By effecting a behavior in the new operating system that corresponds to the behavior that occurred during the execution of the application program under the old operating system, the execution of the application program on the new operating system is simulated. Testers of the new operating system can then compare the output of the simulation to ensure that it correctly corresponds to the execution of the application program under the old operating system. Also, the return parameters from the functions of the new operating system can be compared to the recorded returned parameters from the function of the old operating system to determine whether the new operating system is working correctly. Also, the time taken to perform the functions on the new operating system can be compared to the time taken to perform the functions in the old operating system. Figures 2A, 2B, and 2C are block diagrams illustrating the recording of the interaction and the simulation of an application program. Figure 2A illustrates the interaction between application program 210 and an old operating system 220. The GUI application program 210 invokes the functions of the old operating system 220, and the old operating system 220 invokes the callback routines of the GUI application program 210. Figure 2B illustrates the logging of the invocations of the functions and the callback routines during the execution of the application program 210. When the application program 210 invokes a function, the logger 230 records the passed parameters for the function and the function name to a log file 240. When the function returns to the application program, the logger also records all returned parameters to the log file. When the old operating system 220 invokes a callback routine, the logger 230 records a callback routine identifier and the passed parameters. When the callback routine returns to the old operating system 220, the logger records the returned parameters to the log file. The time associated with each interaction is recorded. Figure 2C is a block diagram illustrating the simulation of the execution of the application program 210 that is recorded in the log file. To simulate the execution of the application program 210, the synthetic GUI application 250 (SGA) inputs the log file that records the execution. The SGA simulates each function invocation represented in the log file by invoking none, one, or more functions of the new operating system 260. The SGA simulates the behavior of the function invocation based on the recorded passed parameters. The SGA 250 also provides a thunk callback routine for each real callback routine of the application program. The SGA 250 passes these thunk callback routines to the new operating system 260. When the new operating system 260 invokes a thunk callback routine, the thunk callback routine simulates the processing of the real callback routine based on the information in the log file. Specifically, the thunk callback routine may simulate the posting and sending of messages and the invoking of functions that occurred during the execution of the real callback routine. The Logger Figure 3 is a block diagram illustrating a preferred architecture of the logger. For each function 221 that the old operating system 220 provides, the logger provides a substitute function 311. The logger also provides a substitute callback routine 312 for each callback routine of the application program. When the GUI application program 210 is initially loaded, all function calls by the application program link to a substitute function 311, rather than the real function 221 in the old operating system. When the application program 210 invokes a function, the substitute function records the invocation to a log file along with each passed parameter and the current time. The substitute function then invokes the real function of the old operating system 220 with the passed parameters. When the real function returns to the substitute function, the substitute function records the return along with the returned parameters to the log file and the current time. The substitute function then returns to the application program with the parameters returned by the real function. In this way, the recording of the log file is functionally transparent to the application program. The real functions of the old operating system are typically stored in a dynamic link library. The executable file containing the application program contains the name of each dynamic link library that the application program invokes. During initial loading of the application program, each invocation of a real function is bound to the real function in the dynamic link library. In a preferred embodiment, each dynamic link library with real functions is associated with a substitute dynamic link library and is given a name with the same number of characters as the name of the "real" dynamic link library and a slight variation of the name of the real dynamic link library. For example, the name "Zernel" may be given to the substitute dynamic link library corresponding to the real dynamic link library "Kernel." When the execution of the application program is to be logged, each real dynamic link library name in the executable file is replaced by a substitute dynamic link library name. Thus, when the application program is loaded, the application program dynamically links to the substitute dynamic link libraries, rather than the real dynamic link libraries. The addresses of callback routines are typically specified to the old operating system by a parameter passed to a function. For example, the address of a window procedure callback routine is specified to the old operating system as a parameter when invoking the function RegisterClass. The substitute function associated with each real function, that is passed as a callback routine, substitutes a substitute callback routine for the real callback routine. The substitute function invokes the real function specifying the substitute callback routine 312 rather than the real callback routine 211. When the old operating system 220 sends a message to the application program 210, it invokes the substitute callback routine 312. The substitute callback routine records the invocation of the callback routine along with the passed parameters and the current time. The substitute callback routine then invokes the real callback routine 211 with the passed parameters. When the real callback routine returns to the substitute callback routine, the substitute callback routine records the return along with the returned parameters. The substitute callback routine then returns to the old operating system with the returned parameters. When a substitute function or a substitute callback routine records its invocation, it also records a nesting level. The nesting level indicates the level of invocations of the functions and callback routines. For example, when an application program invokes the function DispatchMessage, the nesting level is 1 because no other function or callback routine is currently invoked. If, during the execution of the function DispatchMessage, the function invokes a callback routine, then the nesting level of the callback routine is 2. If that callback routine then invokes a function (e.g., function DefWindowProc), then the invocation of that function is at nesting level 3. If the function at nesting level 3 invokes a callback routine, then the nesting level of the callback routine is 4, and so on. Alternatively, the nesting level of an invocation can be determined from the log after completion of the execution of the application program, rather than during execution. Figure 4 is a flow diagram of a sample substitute function. The substitute function has the same calling prototype (that is, the same function type and the same number and type of parameters) as the real function. In a preferred embodiment, the substitute function is generated automatically from a "header" file that defines the original function to the application. The substitute function records the invocation of the function along with the passed parameters and the current time and the return of the function along with the returned parameters and the current time. The substitute function invokes the real function. The substitute function ensures that the real function is passed the same parameters that it receives, and ensures that the application program is returned the same parameters that the real function returns. In step 401, the substitute function saves the current state of the CPU, which may include saving the registers. The substitute function ensures that CPU state is restored to this saved state before the real function is invoked. In step 402, the substitute function increments the nesting level. In step 402A, the substitute function retrieves the current time. In step 403, the substitute function records the function invocation and passed parameters and the current tame. In step 404, the substitute function restores the state of the CPU to the state saved in step 401. In step 405, the substitute function invokes the real function with the passed parameters. In step 406, the substitute function saves the state of the CPU upon return from the real function. The substitute function ensures that the CPU state is restored to this saved state before the substitute function returns. In step 406A, the substitute function retrieves the current time. In step 407, the substitute function records the return and returned parameters and the current time. In step 408, the substitute function decrements the nesting level. In step 409, the substitute function restores the CPU state saved In step 406 and returns to the application program. Figure 5 is a flow diagram of a routine to record a function invocation to a log file. The routine writes an identification of the real function (e.g., function name) to the log file along with all the parameters passed to the real function and the current time. The log file preferably includes an entry (e.g., a line) for each recorded invocation and return of a function or callback routine. Each entry identifies whether it corresponds to an invocation or return of a function or callback routine. In step 501, the routine writes the nesting level and function invocation identifier (e.g., "APICALL") to the log file and the current time. In step 502, the routine writes the function name (e.g., "RegisterClass") to the log file. In steps 503 through 505, the routine loops writing the passed parameters to the log file. The routine must write all the information to the log file that the real function may use when it executes. For example, if the real function prints a buffer of data to the display monitor, then the buffer may be pointed to by a pointer. The routine copies all the data in the buffer to the log file, not just the pointer. This actual data can then be redisplayed during simulation. In step 503, if all the parameters have been processed, then the routine returns, else the routine continues at step 504. In step 504, the routine retrieves the next parameter. In step 505, the routine processes the retrieved parameter and writes the data associated with the parameter to the log file, and then loops to step 503. Figure 6 is a flow diagram illustrating the recording of a typical integer parameter that is passed by value. The value of the parameter is retrieved and written to the log file. Figure 7 is a flow diagram illustrating a routine that records a parameter that is passed as a pointer to a buffer. The routine not only records the data pointed to by the passed pointer (the buffer), but also records any data pointed to by pointers in the buffer. In step 701, the routine writes a left brace to the log file. The left brace indicates the start of data that is pointed to. In step 702, if the next data item is a pointer, then the routine continues at step 704, else the routine continues at step 703. In step 703, the routine writes the non-pointer parameter to the log file. In step 704, the routine recursively calls itself to process the pointer. In step 705, if all the parameters have been processed, then the routine continues at step 706, else the routine loops to step 702. In step 706, the routine writes a right brace to the log file and returns. Figure 8 is a flow diagram of the processing of a parameter that points to a callback routine. In a preferred embodiment, each substitute function that is passed a callback routine includes an array of substitute callback routines. Each time the substitute function is invoked, it selects the next substitute callback routine in the array as the substitute for the passed callback routine. The substitute function also maintains a table that correlates each real callback routine to its substitute callback routine. For example, the substitute function for the function RegisterClass preferably contains an array of identical substitute window procedures. When each new window class is registered, the next unused substitute window procedure in the array is selected. Alternatively, a substitute function could create the substitute callback routines as needed. In step 801, the routine selects an unused substitute callback routine. In step 802, the routine maps the real callback routine to the substitute callback routine. In step 303, the routine substitutes the address of the substitute callback routine for the address of the real callback routine in the parameter list and returns. Figure 9 is a flow diagram of a typical substitute callback routine. The typical substitute callback routine is analogous to the typical substitute function as shown in Figure 4. In step 901, the substitute callback routine saves the CPU state. In step 902, the substitute callback routine increments the nesting level. In step 902A, the substitute callback routine retrieves the current time. In step 903, the substitute callback routine records the invocation of the callback routine along with the passed parameters and current time to the log file. In step 904, the substitute callback routine finds the address of the associated real callback routine. In step 905, the substitute callback routine restores the CPU state to the state that was saved in step 901. In step 906, the substitute callback routine invokes the real callback routine. In step 907, the substitute callback routine saves the CPU state returned by the real callback routine. In step 907A, the substitute callback routine retrieves the current time. In step 908, the substitute callback routine records the return of the callback routine along with the returned parameters and current time to the log file. In step 909, the substitute callback routine decrements the nesting level. In step 910, the substitute callback routine restores the CPU state to the state that was saved in step 907 and the substitute callback routine returns to the invocation by the operating system. Table 1 contains a sample application program written in the "C" programming language. The application program creates and displays an instance of a window class named "Generic2Class" with the window procedure named "MainWndProc". The window procedure handles the messages WM_COMMAND, WM_DESTROY, WM_PAINT, AND WM_LBUTTONDOWN. All other messages are passed by the window procedure to the operating system using the function DefWindowProc. The window procedure when sent a WM_COMMAND message with the IBM_ABOUT parameter invokes the function DialogBox with a pointer to the callback routine to handle messages to the dialog box. Table 2 contains a section of a log file for an execution of the sample application program of Table 1. Table 2 contains an entry (line) for each function and callback routine invocation and return. Each entry contains a line number (for reference), a nesting level, a vertical bar, timing information, another vertical bar, an identifier of the type of entry, the function name or callback routine identifier, and the parameters. For example, line number 7 contains an entry corresponding to an invocation of the function CreateWindow. The nesting level is 1. The function was invoked at time "942102B3". The entry type is "APICALL", which indicates the invocation of a function. The parameters are "Generic2Class", "Generic Sample Application", "CF00", etc. The entry corresponding to the return of the function CreateWindow is at line 24. Note that each nesting level in between lines 7 and 24 is at a level greater than 1. During the invocation of the function CreateWindow, the operating system sent the message "WM_GETMINMAXINFO" to the callback routine passed to the function CreateWindow as indicated at line 8. An entry type corresponding to the invocation of a callback routine is "MSGCALL". The Synthetic GUI Application Once a log file for the execution of an application program is generated, the execution of the application program can be simulated on a new operating system. The synthetic GUI application (SGA) program reads in the log file and simulates the recorded behavior by invoking the functions of the new operating system or some other existing operating system. By simulating the behavior of the application program, the new operating system can be tested to ensure its functions perform correctly. The SGA program provides a thunk function for every real function of the old operating system. The thunk function simulates the execution of the real function on the new operating system by invoking the functions of the new operating system. If the new operating system has a function whose behavior corresponds to the behavior of the function of the old operating system, then the thunk function can use the function of the new operating system to simulate the behavior. However, if there is no corresponding function of the new operating system, then the thunk function may have to invoke several functions of the new operating system to simulate the behavior. Each thunk function that corresponds to a real function, that is passed a callback routine, provides a thunk callback routine. The thunk callback routine simulates the behavior of the corresponding real callback routine in the application program. Each thunk callback routine, when invoked by the new operating system, invokes an SGAEngine routine, as described below, to simulate the behavior of the application program. Figure 10A is an overview diagram illustrating the synthetic GUI application (SGA). The SGA 1010 comprises the SGAEngine routine 1050, thunk functions 1060 for each real function of the old operating system, and thunk callback routines 1070 corresponding to real callback routines of the new operating system. The new operating system 1020 comprises real functions 1030 and a window class table 1014. The SGA 1010 reads the log file and simulates the execution of the recorded application program. Each recorded invocation of a function is simulated by invoking the corresponding thunk function with the recorded passed parameter(s). The behavior of each invocation of a callback routine is simulated by a thunk callback routine. The SGAEngine routine 1050 controls the simulation. The routine is passed a message and simulates the execution of that message. The routine scans the log file for the invocation of a callback routine through which the message is sent to the application. The routine then simulates the execution of each invocation of a function that is nested within that callback routine. For example, if the SGAEngine routine is invoked for the message WM_CREATE corresponding to line 20, then the routine simulates the nested invocation of the function DefWindowProc at line 21. The SGAEngine routine retrieves the passed parameters from the log file and invokes functions of the new operating system to simulate the behavior of the function of the old operating system. When the function of the new operating system is complete, the SGAEngine routine determines whether the returned parameters compare to the logged returned parameter. If the parameters do not compare, then the difference is noted. Optionally, timing information about the invocation on the new operating system can be recorded in a separate new log file. Figure 10B is a flow diagram of the synthetic GUI application program. The synthetic GUI application (SGA) inputs a log file and simulates the execution of the GUI application program recorded in the log file by invoking functions of a new operating system. In step 1001, the SGA generates a sent message file (SMF). The sent message file contains an entry for each sent message recorded in the log file. Each entry in the sent message file contains an identifier of the message, the line number of the message in the log file, and a handle identifying the resource (e.g., window, dialog box) to which the message is directed. Table 3 is a sample sent message file generated for the log file of Table 2. Line number 5 of the sent message file contains the entry "WM_CREATE 20, 8A", which indicates that line number 20 of the log file records that a WM_CREATE was sent to the window with handle 8A. In step 1002, the SGA generates a posted message file (PMF). The posted message file contains an entry for each posted message recorded in the log file. Each entry in the posted message file contains the message name, the line number corresponding to the retrieval of the message, the line number where the event corresponding to the posted message should be simulated, and a handle identifying the resource (e.g., window, dialog box) to which the message is directed. Table 4 contains a sample posted message file for the log file of Table 2. Line number 5 in the posted message file contains the entry "WM_KEYDOWN 192, 187, 8A", which indicates that line number 192 in the log file records at a WM_KEYDOWN message was retrieved by the window procedure for the window with handle 8A and that the posting of the message should be simulated at line 187. Alternatively, a sent message file and a posted message file is generated by the logger during the execution of the application program. In step 1003, the SGA invokes a SGAEngine routine to simulate execution of the application program. Figure 11 is a flow diagram of the routine GenerateSentMessageFile. The sent message file is generated to improve the processing efficiency of the SGAEngine routine. In step 1101, the routine writes an initialization message (INIT) to the sent message file. This initialization message is used as an indication to initialize the SGAEngine routine. In steps 1102 through 1105, the routine loops searching for invocations of a callback routine and writes entries to the sent message file. In step 1102, the routine searches the log file for the next entry corresponding to the invocation of a callback routine. In step 1103, if the end of the log file is reached, then the routine returns, else the routine continues at step 1104. In step 1104, the routine writes the message, the line number of the entry, and the handle of the resource to which the message is directed to the sent message file and loops to step 1101. Figure 12 is a flow diagram of the routine GeneratePostedMessageFile. This routine searches the log file for each posted message and determines when the posted message should be simulated by the SGA. In step 1201, the routine searches for the next invocation of the function GetMessage, which retrieves posted messages in the log file, or function PeekMessage, which looks at posted messages and may or may not retrieve them. In step 1202, if the end of the log file is reached, then the routine returns, else the routine continues at step 1203. In step 1203, the routine records the line number in the log file corresponding to the invocation of the function GetMessage or PeekMessage. This line number indicates the point at which the event corresponding to the posted message should be simulated. For example, if the posted message is WM_KEYDOWN, then the WM_KEYDOWN message should be simulated before the SGA simulates the execution of the function GetMessage that retrieves the WM_KEYDOWN message or before the execution of the function PeekMessage, which may or may not have noticed its presence in the message queue. In step 1204, the routine searches the log file for an entry corresponding to the invocation of a callback routine that matches the posted message. That is, the invocation of the callback routine through which the posted message was sent to the application program. In step 1205, the routine records the line number of the entry in the log file corresponding to the invocation of the callback routine. In step 1206, the routine writes the message, message line number, post line number, and the handle of the resource to which the message is directed to the posted message file and loops to step 1201. In an alternate embodiment, the sent message and posted message files are generated during a single pass of the log file. Also, the sent message and posted message files need not be generated, rather the information can be determined from the log file as the simulation proceeds. Figure 13 is a flow diagram of the SGAEngine routine. This routine is passed a window handle and a message. The routine simulates the application program processing of that message as recorded in the log file. The routine determines which entry in the log file corresponds to the passed message. In a preferred embodiment, this determination selects the first entry in the log file of a message of the same type as the passed message and with the same handle to a resource. The routine then simulates the execution of the application program that occurs in response to the receipt of the message. The execution that occurs in response is represented by the entries in the log file that are nested within the invocation of the callback routine that processes the message. The SGAEngine routine is called recursively to process nested messages. To initiate the SGAEngine routine, a dummy entry is stored at line number 0 in the log file at nesting level 0 and corresponding to the sending of the message INIT. The SGAEngine routine simulates execution of all entries in the log file nested within nesting level 0, which is the entire log file. In step 1301, the routine finds the message in the sent message file that corresponds to the passed message and records that message line. In step 1302, the routine determines the nesting level of the found message. In step 1303, the routine validates the passed parameters. In step 1304, the routine searches for the next line in the log file that corresponds to an invocation of a function within the callback routine that processed the passed message. The routine records that line number as the call line. For example, if the passed message corresponds to the message at line number 8 of the log file, then line number 9 contains a nested function invocation. In step 1305, if the routine finds a next line, then the routine continues at step 1306, else the routine continues at step 1310. In step 1306, the routine invokes routine SimulatePostedMessage to simulate the posting of a message, if appropriate. In step 1307, the routine finds the line corresponding to the return of the nested function invocation. In step 1308, the routine retrieves or identifies the thunk function for the nested function. In step 1309, the routine invokes the thunk function and loops to step 1304. In step 1310, the routine finds the return line associated with the invocation line of the message found in step 1301. In step 1311, the routine sets the appropriate return values and returns. Figure 14 is a flow diagram of the routine FindMessageInSentMessageFile. This routine is passed a message and a resource (window) handle. This routine finds the next message in the sent message file that corresponds to the passed message for the passed resource handle. The routine returns the line number in the log file of the message. The routine maintains an array to track the last entry in the sent message file found for each message type for each resource handle. The routine starts the search from the last entry. In step 1401, the routine retrieves the message line of the last message found in the sent message file for the passed resource handle of the passed message type. In steps 1402 through 1403, the routine loops searching the sent message file for the next message of the passed message type for the passed resource handle. In step 1402, the routine increments the message line. In step 1403, if the message of the message line in the sent message file equals the passed message type and passed resource handle, then the routine continues at step 1404, else the routine loops to step 1402. In step 1404, the routine sets the last message line number for the passed message type and passed resource handle to the message line. In step 1405, the routine retrieves the line number in the log file of the entry corresponding to the invocation of the callback routine to process the passed message and returns. Figure 15 is a flow diagram of the routine SimulatePostedMessage. This routine scans the posted message file to determine if the posting of a message should be simulated before the SGA simulates the execution of the function corresponding to the entry in the log file at the passed line number. The routine then simulates the posting of the message, if appropriate. In step 1501, the routine scans the posted message file to determine whether a message should be posted before simulation of the entry at the passed line number in the log file. In step 1502, if a message should be posted, the routine continues at step 1503, else the routine returns. In step 1503 through 1510, the routine determines which message should be posted and calls the appropriate routine to simulate the posting of the message and the routine then returns. Figure 16 is a flow diagram of a routine that simulates the posting of the WM_KEYDOWN message. The routine is passed the sent line corresponding to the invocation of the callback routine and the post line number corresponding to the line number before which the message should be posted. In step 1601, the routine retrieves the message at sent line from the log file. In step 1602, the routine calls the function PostMessage or the new operating system or its equivalent to post the retrieved WM_KEYDOWN message and the routine returns. Figure 17 is a flow diagram of a routine that simulates a WM_MOUSEMOVE message. The routine is passed the sent line number in the log file of the entry corresponding to the invocation of the callback routine and the post line number corresponding to the line number before which the posting of the message should be simulated. To simulate a WM_MOUSEMOVE message, the routine simulates the sent messages that were sent during the invocation of the function GetMessage that retrieved the posted WM_MOUSEMOVE message. The routine then posts the WM_MOUSEMOVE message to the new operating system. For example, line number 136 of the log file corresponds to the sending of a WM_MOUSEMOVE message and line number 123 corresponds to the line before which the posting of the WM_MOUSEMOVE message should be simulated. To simulate the WM_MOUSEMOVE message, the sending of the WM_NCHITTEST message at line 124 and the sending of the WM_SETCURSOR message at line 128 should be simulated. This routine uses the function SendMessage (or its equivalent) in the new operating system to send these messages. The thunk callback routines are then invoked by the new operating system to send the message to the SGA. After the messages are sent, then the SGA posts the WM_MOUSEMOVE message by invoking the function PostMessage (or its equivalent) in the new operating system. In steps 1701 through 1704, the routine retrieves each sent message and sends the message to the new operating system. In step 1701, the routine sets the start of the search at the post line. In step 1702, if the search line in the log file indicates the return from the invocation of the function GetMessage at the post line, then the routine continues at step 1705, else the routine continues at step 1703. In step 1703, the routine retrieves the next sent message from the log file. In step 1704, the routine calls the function SendMessage of the new operating system with the retrieved message and loops to step 1702. In step 1705, the routine retrieves the message corresponding to the return from the invocation of the function GetMessage at the post line. In step 1706, the routine calls the function PostMessage of the new operating system with the retrieved message and returns. Alternatively, the routine that simulates a WM_MOUSEMOVE message could invoke a function SetCursorPos of the new operating system, which effectively simulates a WM_MOUSEMOVE message. Figure 18 is a flow diagram of a thunk window procedure. Each thunk callback routine operates in a similar way. In step 1801, the routine determines which old window handle corresponds to the window handle passed by the new operating system. The new operating system uses handles that do not necessarily correspond to the actual handles used by the old operating system. Consequently, the SGA maintains a mapping between handles of the old operating system and corresponding handles in the new operating system. In step 1802, the routine invokes the SGAEngine routine to simulate the processing of the window procedure by the application program and returns. Figure 19 is a flow diagram of the routine ThunkRegisterClass. In step 1901, the routine selects the next unused thunk window procedure. In step 1902, the routine establishes a correspondence between the class name and the selected thunk window procedure. Every time a window is created of this class, the selected window procedure is used as the thunk window procedure based on this correspondence. In step 1903, the routine retrieves the parameters for the invocation of the function RegisterClass from the log file at the line number indicated by the passed call line. In step 1904, the routine sets the address of the window procedure to that of the selected thunk window procedure. In step 1905, the procedure calls the function RegisterClass of the new operating system. In step 1906, the routine determines if the return values of the invocation of function RegisterClass for the new operating system corresponds to the return values of the invocation of the function RegisterClass for the old operating system as indicated by the return line in the log file and reports an error message if they do not correspond. The routine then returns. Figure 20 is a flow diagram of the routine ThunkCreateWindow. In step 2001, the routine retrieves the passed parameters for the invocation of function CreateWindow from the log file at the line number indicated by the passed call line. In step 2002, the routine determines the new window handle for the passed parent window, if one has been assigned. In step 2003, the routine determines the new menu handle of the passed menu, if one has been assigned. In step 2004, the routine determines the new handle for the instance of this application, the SGA. In step 2005, the routine gets the return parameters from the log file at the line number indicated by the passed return line. In step 2006, the routine calls the function CreateWindow of the new operating system passing the new parameters (e.g., new handles). In step 2007, the routine establishes the correspondence between the new handle returned by the new operating system and the old handle used by the old operating system as indicated by the return parameters in the log file. In step 2008, the routine determines whether the return parameters from the invocation of the function CreateWindow of the new operating system corresponds to the return parameters of the invocation of function CreateWindow in the old operating system as indicated by the return line in the log file and reports an error if they do not correspond. The routine then returns. Figure 21 is a flow diagram of the procedure ThunkDestroyWindow. In step 2101, the routine retrieves the passed parameters from the log file at the line number indicated by the passed call line. In step 2102, the routine determines the new window handle that corresponds to the old window handle. In step 2103, the routine retrieves the returned parameters from the log file at the line number indicated by the passed return line. In step 2104, the routine invokes the function DestroyWindow of the new operating system. In step 2104, the routine compares the return value of the invocation of the function DestroyWindow of the new operating system with the invocation of the function DestroyWindow of the old operating system as indicated by the retrieved return parameters and reports an error if there is a difference. The routine then returns. Figure 22 is a flow diagram of a template thunk function. The thunk function is passed the line number in the log file corresponding to an invocation (call line) and return (return line) of the function. In steps 2201 through 2202, the thunk function retrieves the passed parameters from the log file. In steps 2203 through 2204, the thunk function retrieves the returned parameters from the log file. In step 2205, the thunk function retrieves the new handles that correspond to any old handle passed as a parameter. In step 2206, the routine invokes functions to simulate the function in the old operating system in the new operating system. In step 2207, the thunk function sets the correspondence between any new handles returned by the new operating system and the old handles of the old operating system. In step 2208, if the returned parameters from the simulated function do not correspond to the return parameters from the log file, then an error is reported in step 2209 and then the routine returns. Figure 23 is a block diagram of an alternate embodiment of the present invention. A real-time logger 2302 intercepts service requests (function calls) of an application program 2301 intended for an old server program and sends the request to a simulator program 2303. The simulator program maps the received requests to service requests of the new server program 2304. The new server program performs these requests and passes results through the simulator to the real-time logger, which returns to the application program. Similarly, when the new server program invokes a callback routine, the simulator program routes the invocation to the logger which invokes the appropriate callback routine of the application program. The new server program inputs external events and routes indicators of events to the application program through the simulator and real-tame logger. One skilled in the art would appreciate that methods and systems of the present invention can be used to simulate the execution of programs that use an API provided by other than an operating system in conjunction with a graphical user interface. For example, a database system (server program) may provide various functions that comprise its API. The interaction between application programs (client program) and the database system can be recorded during an execution of the application program. This recorded interaction can then be used to simulate the application program and to test a new database system. One skilled in the art would also appreciate that the new operating system could be simply the old operating system with certain functions rewritten, enhanced, or modified. In this case, although existing application programs can execute under the new operating system, the simulation system can be used to check the parameters returned by functions of the new operating system and parameters passed to callback routines by the new operating system. One skilled in the art would further appreciate that the present invention can be used to compare the performance of a client program developed to request services of a first server program with simulated performance on a second server program. To compare performances, the client program is executed and a log is generated. The execution is simulated on both the first and second server programs and performance characteristics are recorded. The performance characteristics include simulation overhead for both server programs to provide a normalized basis for comparison. Alternatively, a similar approach can be used to compare the performance with a third server program. Although the present has been described in terms of a preferred embodiment, it is not intended that the invention be limited to this embodiment.

Claims: A method in a computer system for simulating an execution of a client program, the client program for invoking functions of a first server program, the client program specifying parameters for identifying variations in behavior of invoked functions, the method comprising the steps of: during execution of the client program (10), logging a plurality of invocations made by the client program of functions of the first server program (20), each invocation including an identification of the function and any parameters specified with the invocation; and invoking functions of a second server program (60) to perform a behavior similar to the behavior performed by the first server program (20) based on the logged invocations whereby the behavior of the client computer program (10) is simulated. The method of claim 1 wherein the step of invoking functions of the second server program (60) to perform a behavior includes the steps of: for each of a plurality of logged invocations (40), selecting one or more functions of the second server program (60) to simulate the behavior of the logged invocation; and invoking the selected functions of the second server program (60) to effect simulation of the behavior of the logged invocation (40). The method of claim 2 wherein the step of invoking the selected functions of the second server program (60) includes the step of passing to the second server program any parameters specified with the logged invocation. The method of claim 3 including the step of before passing a parameter to a function of the second server program (60), mapping the parameter from a parameter generated by the first server program (20) to a parameter generated by the second server program. The method of claim 4 wherein the step of mapping includes the step of mapping a computer system generated handle. The method of claim 1 wherein the step of invoking functions of the second server program to perform a behavior includes the steps of: associating a thunk function with each function provided by the first server program each thunk function (1060) having a prototype similar to the prototype of the associated function of the first server program; and invoking the thunk function (1060) associated with the function of a logged request to simulate behavior of the logged request. The method of claim 6 wherein the step of invoking the thunk function (1060) includes the step of passing a parameter analogous to a parameter of the logged request. The method of claim 7 including the step of before passing a parameter to the second server program (60), mapping the parameter from a parameter generated by the first server program to a parameter generated by the second server program. The method of claim 6 including the step of: during the invocation of the thunk function (1060), invoking one or more functions of the second server program (60) to simulate the behavior of the function associated with the thunk function. The method of claim 9 including the step of: upon return from a function of the second server program (60), specifying return parameters to be returned by the thunk function (1060). The method of claim 1 wherein the step of logging a plurality of invocations made by the client program (10) of functions of the first server program (20) includes the step of logging each return from an invoked function (40), each logged return including an identification of the invoked function and any parameter returned by the invoked function. The method of claim 1 wherein the step of logging a plurality of invocations made by the client program of functions includes the step of sending indications of the invocations to a simulation program that controls the invoking of functions of the second server program (60). The method of claim 1 wherein the step of logging includes logging invocations of callback routines of the client program (10), and including associating a thunk callback routine with each callback routine wherein the thunk callback routine simulates behavior of the associated callback routine when invoked by the first server program. The method of claim 1 wherein the first server program is an operating system and the second server program (60) is a different version of the same operating system. The method of claim 1 wherein the first server program (20) is an operating system and the second server program (60) is a different operating system. A computer system for comparing the performance between execution of a client program (10) with a first server program (20) and execution of the client program with a second server program (60), the client program for requesting services of a third server program (20), the system comprising: a logging component (40) that, during an execution of the client program, logs a plurality of requests for a service of the third server program, each request including an identification of the requested service; a simulation component (50) that simulates the execution of the client program with the first server program (20) by selecting logged requests, requesting the first server program to perform the requested behavior of each selected logged request, and recording characteristics of the performance of the request by the first server program; and simulates the execution of the client program with the second server program (60) by selecting logged requests, requesting the second server program to perform the requested behavior of each selected logged request, and recording characteristics of the performance of the request by the second server program; and an analysis component that analyzes the recorded characteristics of the performance of requests by the first server program and the second server program. The system of claim 16 wherein the recording the performance characteristics record timing information. The system of claim 17 wherein the simulating the execution of the client program with the first server program (20) are performed on a first computer and the simulating the execution of the client program with the second server program is performed on a second computer, the first computer and the second computer having different architectures. The system of claim 18 wherein the logging is performed on a third computer having an architecture different from the architecture of the first computer and the second computer.

Inventors: BLAKE RUSSEL P, DAY ROBERT F, BLAKE, RUSSEL P., DAY, ROBERT F.
Applicants: MICROSOFT CORP, MICROSOFT CORPORATION
Application year: 1994
Main classification: G06F11
IPC codes: G06F9, G06F11