// $Id$ // ============================================================================ // // = LIBRARY // tests // // = FILENAME // CDR_File_Test.cpp // // = DESCRIPTION // Checks the functionality of the ACE CDR streams used for file // I/O. // // = AUTHORS // Giga Giguashvili and // Douglas C. Schmidt // // ============================================================================ #include "test_config.h" #include "ace/OS_Memory.h" #include "ace/OS_NS_stdlib.h" #include "ace/OS_NS_string.h" #include "ace/CDR_Stream.h" #include "ace/FILE_Connector.h" #include "ace/Auto_Ptr.h" #include "ace/Get_Opt.h" #include "ace/ACE.h" // FUZZ: disable check_for_streams_include #include "ace/streams.h" ACE_RCSID(tests, CDR_File_Test, "$Id$") #if !defined (ACE_LACKS_IOSTREAM_TOTALLY) | defined (ACE_HAS_WINCE) #if defined (ACE_HAS_WINCE) #include "CE_fostream.h" #endif // ACE_HAS_WINCE class CDR_Test { // = TITLE // Simple class that's used to read and write CDR streams. friend ostream& operator << (ostream &os, const CDR_Test &t); // Output the state of a object to the . friend void operator << (ACE_OutputCDR &os, const CDR_Test &t); // Convert the state of this object into an . friend void operator >> (ACE_InputCDR &is, CDR_Test &); // Convert the into the state of this object. public: CDR_Test (void); // Default constructor. CDR_Test (ACE_CDR::Char o, ACE_CDR::Short s, ACE_CDR::Long w, ACE_CDR::ULongLong lw, ACE_CDR::Float f, ACE_CDR::Double d); // Constructor. bool operator == (const CDR_Test &rhs) const; // Compare for equality with . private: ACE_CDR::Char char_; ACE_CDR::Short word2_; ACE_CDR::Long word4_; ACE_CDR::ULongLong word8_; ACE_CDR::Float fpoint_; ACE_CDR::Double dprec_; }; ostream & operator << (ostream &os, const CDR_Test &t) { os << "Char: " << t.char_ << endl << "Short: " << t.word2_ << endl << "Long: " << t.word4_ << endl; ACE_CDR::ULongLong hi = (t.word8_ >> 32); ACE_CDR::ULongLong lo = (t.word8_ & 0xffffffff); os << "ULongLong 1st half: " << hex << ACE_U64_TO_U32 (hi) << dec << endl << "ULongLong 2nd half: " << hex << ACE_U64_TO_U32 (lo) << dec << endl << "Float: " << t.fpoint_ << endl << "Double: " << t.dprec_ << endl; return os; } CDR_Test::CDR_Test (void) : char_ (0), word2_ (0), word4_ (0), word8_ (0), fpoint_ (0.0), dprec_ (0.0) { } CDR_Test::CDR_Test (ACE_CDR::Char o, ACE_CDR::Short s, ACE_CDR::Long w, ACE_CDR::ULongLong lw, ACE_CDR::Float f, ACE_CDR::Double d) : char_ (o), word2_ (s), word4_ (w), word8_ (lw), fpoint_ (f), dprec_ (d) { } void operator << (ACE_OutputCDR &os, const CDR_Test &t) { os << t.char_; os << t.word2_; os << t.word4_; os << t.word8_; os << t.fpoint_; os << t.dprec_; } void operator >> (ACE_InputCDR &is, CDR_Test &t) { is >> t.char_; is >> t.word2_; is >> t.word4_; is >> t.word8_; is >> t.fpoint_; is >> t.dprec_; } bool CDR_Test::operator == (const CDR_Test &rhs) const { // @@ Workaround bug in egcs-1.1.1 using a single && expression // results in UMR errors in purify. if (this->char_ != rhs.char_) return false; if (this->word2_ != rhs.word2_) return false; if (this->word4_ != rhs.word4_) return false; if (this->word8_ != rhs.word8_) return false; if (this->fpoint_ != rhs.fpoint_) return false; if (this->dprec_ != rhs.dprec_) return false; return true; } static int run_test (int write_file, ACE_FILE_IO &file, const ACE_TCHAR *filename, CDR_Test &cdr_test) { if (write_file) { char byte_order = ACE_CDR_BYTE_ORDER; size_t n = file.send (&byte_order, 1); if (n != 1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("send failed on %p\n"), filename), -1); ACE_OutputCDR output_cdr (0, ACE_CDR_BYTE_ORDER, 0, 0, 0, ACE_DEFAULT_CDR_MEMCPY_TRADEOFF, ACE_CDR_GIOP_MAJOR_VERSION, ACE_CDR_GIOP_MINOR_VERSION); // Marshal the object data to the output CDR stream. output_cdr << cdr_test; // Output the data to cout. #if defined (ACE_HAS_WINCE) && defined (ACE_LACKS_IOSTREAM_TOTALLY) // Since CE does not have ostream, ace_file_stream and output_file() cannot // be used. Just use 'hard-coded' file name here. (*ACE_CE_OSTREAM::instance()).open(ACE_TEXT("\\Log\\CDR_File_Test.txt")); (*ACE_CE_OSTREAM::instance()) << cdr_test; #else *ace_file_stream::instance ()->output_file () << cdr_test; #endif // ACE_HAS_WINCE // Save the data. const ACE_Message_Block *output_mb = output_cdr.begin (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Writing file %s in %s endian format...\n"), filename, ACE_CDR_BYTE_ORDER ? ACE_TEXT("little") : ACE_TEXT("big"))); n = file.send (output_mb->rd_ptr (), output_mb->length ()); if (n != (size_t) output_mb->length ()) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("send failed on %p\n"), filename), -1); } else // We're reading from the file. { ACE_FILE_Info info; if (file.get_info (info) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("get_info failed on %p\n"), filename), -1); size_t msgsize = info.size_ - 1; // Allocate the input buffer char *buffer = 0; ACE_NEW_RETURN (buffer, char[msgsize], -1); #if defined (ACE_INITIALIZE_MEMORY_BEFORE_USE) ACE_OS::memset(buffer, 0, sizeof (buffer)); #endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */ // Make sure is released automagically. ACE_Auto_Basic_Array_Ptr b (buffer); // Move the file pointer back to the beginning of the file. if (file.seek (0, SEEK_SET) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), filename), -1); char byte_order; size_t size = file.recv (&byte_order, 1); if (size != 1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Read %d bytes, rather than expected ") ACE_TEXT ("1 bytes\n"), size), -1); // Read the cdr data from the file into the buffer. size = file.recv (buffer, msgsize); if (size != msgsize) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Read %d bytes, rather than expected ") ACE_TEXT ("%d bytes\n"), size, msgsize), -1); // Create message block for the whole file. Ensure that it is // aligned to properly handle the double. ACE_Message_Block mb (ACE_CDR::MAX_ALIGNMENT + msgsize); ACE_CDR::mb_align (&mb); mb.copy (buffer, msgsize); // Create CDR input stream from the message block. ACE_InputCDR input_cdr (&mb); input_cdr.reset_byte_order ((int) byte_order); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reading file %s in %s endian format...\n"), filename, ACE_CDR_BYTE_ORDER ? ACE_TEXT("little") : ACE_TEXT("big"))); CDR_Test temp; // Demarshal the data from the input CDR stream into the // object. input_cdr >> temp; #if defined (ACE_HAS_WINCE) && defined (ACE_LACKS_IOSTREAM_TOTALLY) (*ACE_CE_OSTREAM::instance()) << temp; #else *ace_file_stream::instance ()->output_file () << temp; #endif // ACE_HAS_WINCE ACE_ASSERT (temp == cdr_test); } return 0; } static void usage (const ACE_TCHAR *cmd) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("Usage: %s ") ACE_TEXT ("[-f filename [-w|-r]]"), cmd)); ACE_OS::exit (1); } // Main function int run_main (int argc, ACE_TCHAR *argv[]) { ACE_START_TEST (ACE_TEXT ("CDR_File_Test")); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("This is ACE Version %u.%u.%u\n\n"), ACE::major_version (), ACE::minor_version (), ACE::beta_version ())); ACE_Get_Arg_Opt get_opt (argc, argv, ACE_TEXT ("f:rw")); int opt; int reading = 1; int writing = 1; ACE_TCHAR* fn = 0; while ((opt = get_opt ()) != EOF) { switch (opt) { case 'f': fn = get_opt.opt_arg (); break; case 'r': writing = 0; break; case 'w': reading = 0; break; case '?': default: usage (ACE_TEXT("CDR_File_Test")); } } if ((!reading || !writing) && fn == 0) usage (ACE_TEXT("CDR_File_Test")); if (!reading && !writing) usage (ACE_TEXT("CDR_File_Test")); // Create a temporary filename. ACE_FILE_Addr filename (ACE_sap_any_cast (ACE_FILE_Addr &)); if (fn != 0) filename.set (fn); ACE_FILE_Connector connector; ACE_FILE_IO file; // Open up the file. if (connector.connect (file, filename, 0, ACE_Addr::sap_any, 0, ((writing) ? (O_RDWR | O_CREAT) : O_RDONLY), ACE_DEFAULT_FILE_PERMS) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("connect failed for %p\n"), filename.get_path_name ()), 1); #if (!defined (ACE_WIN32) \ || (defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 == 1)) && \ !defined (VXWORKS) # define TEST_CAN_UNLINK_IN_ADVANCE #endif #if defined (TEST_CAN_UNLINK_IN_ADVANCE) if (fn == 0) { // Unlink this file right away so that it is automatically removed // when the process exits. if (file.unlink () == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("unlink failed for %p\n"), filename.get_path_name ()), 1); } #endif CDR_Test cdr_test ('a', 0x00ff, 0xaabbccdd, 0x01234567, 1.54321f, 1.12345); if (writing) { // write the file. run_test (1, file, filename.get_path_name (), cdr_test); } if (reading) { // read the file. run_test (0, file, filename.get_path_name (), cdr_test); } #if !defined (TEST_CAN_UNLINK_IN_ADVANCE) if (fn == 0) { file.close (); if (file.unlink () == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("unlink failed for %p\n"), filename.get_path_name ()), 1); } #endif ACE_END_TEST; return 0; } #else /* ! ACE_LACKS_IOSTREAM_TOTALLY */ int run_main (int, ACE_TCHAR *[]) { ACE_START_TEST (ACE_TEXT ("CDR_File_Test")); ACE_ERROR ((LM_INFO, ACE_TEXT ("iostreams not supported on this platform\n"))); ACE_END_TEST; return 0; } #endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */