/* test rig for libNW functions */ /* caution: will delete the contents of whatever you tell it is the test device */ #include #include #include #include #include #include #include #include /* need this for frobbing the test file */ #include #define TEST_DEVICE "/var/tmp/NW-S23" #define TEST_FILE "test.mp3" /* * The original MP3 code pads out short reads with zeros, which is * fine and sensible for streaming but makes no sense, really, for * file reads. This switches it on and off and adjusts the expected * test results accordingly. */ #ifdef PAD_SHORT_READ #define TEST_FILE_SIZE 703040 #define TEST_FILE_MS 43521 #define TEST_FILE_FRAMES 1682 #else #define TEST_FILE_SIZE 702622 #define TEST_FILE_MS 43495 #define TEST_FILE_FRAMES 1681 #endif void progress( double percent, void *context ) { fprintf( stderr, "\r done %.2f%%", percent * 100 ); } /* * optional args: /path/to/device, testfile, and API version to test * (v1 or v2) */ int main( int argc, char *argv[] ) { nw_device_t *dev = NULL; nw_track_t *track = NULL; FILE *fp = NULL; GList *players = NULL; int retval = 1, i; guint16 test, test2; gchar *testdev = NULL; gchar *testfile = NULL; gchar *buffer = NULL; nw_track_t *tptr = NULL; struct stat statbuf; int nbytes = 0; long offset = 0; unsigned test_file_size = 0; unsigned test_file_ms = 0; unsigned test_file_frames = 0; NWFILE *mfp = NULL; nw_api_t api = NW_GUESS; guint32 frate = 0, framerates[15], flen; mp3file mp3f; struct frame *frm; id3_utf8_t *filename = NULL; signed long taglen; if ( argc > 1 && strlen( argv[1] )) { testdev = g_strdup( argv[1] ); } else { testdev = g_strdup( TEST_DEVICE ); } if ( argc > 2 && strlen( argv[2] )) { testfile = g_strdup( argv[2] ); } else { testfile = g_strdup( TEST_FILE ); } if ( argc > 3 ) { if ( !strcmp( argv[3], "v1" )) { api = NW_MPLE; } else { api = NW_MPLE_V2; } } /* count the frames and such in the test file */ if (( fp = fopen( testfile, "rb" )) == NULL ) { perror( testfile ); goto out; } mp3f.fp = fp; mp3f.fsizeold = 0; mp3f.bsbuf = mp3f.bsspace[1]; mp3f.bsnum = 0; for ( i = 0; i < 15; i++ ) { framerates[i] = 0; } flen = 0; while( mpg123_read_frame( &mp3f, &frm )) { if ( flen == 0 ) { flen = framesize( frm ); frate = tabsel_123[lsf(frm)][2][bitrate_index(frm)]; } test_file_frames++; framerates[15 - bitrate_index(frm)]++; test_file_size += 4; /* frame header */ test_file_size += framesize( frm ); } for ( i = 0; i < 15; i++ ) { test_file_ms += (double)( flen * framerates[i] ) / (double)( frate * 125 ); } test_file_ms *= 1000; fprintf( stderr, "expect : size %u frames %u ms %u\n", test_file_size, test_file_frames, test_file_ms ); fclose( fp ); fp = NULL; /* test for available devices */ fprintf( stderr, "scanning for devices..." ); players = nw_get_devs( NULL ); fprintf( stderr, "done\n" ); if ( g_list_length( players ) == 0 ) { fprintf( stderr, "no NW players found\n" ); } else { GList *p; for ( p = players; p != NULL; p = g_list_next( p )) { nw_device_t *pl = p->data; fprintf( stderr, " %s (%s)\n", (gchar *)nw_get_attr( pl, "device" ), nw_get_attr( pl, "mountpoint" ) == NULL ? "unmounted" : (gchar *)nw_get_attr( pl, "mountpoint" )); nw_dev_free( p->data ); } g_list_free( players ); } fprintf( stderr, "Using %s for tests\n", testdev ); dev = nw_dev_init( testdev, api ); if ( dev == NULL ) { perror( "nw_dev_init" ); goto out; } /* this is a hack to stop the progress bar from trying to display when I compile from within emacs */ if ( getenv( "EMACS" ) == NULL ) { nw_set_progress_func( dev, progress ); } else { fprintf( stderr, "running under EMACS, will not use progress function\n" ); } if ( nw_parse_directory( dev ) == NULL ) { if ( errno && errno != ENOENT ) { perror( "parsing directory" ); goto out; } else { /* empty device */ } } /* make sure the device is empty */ fprintf( stderr, "Making sure device is clean..." ); while( g_list_length( nw_get_folderlist( dev ))) { fprintf( stderr, "." ); if ( nw_del_folder( dev, 1 ) == FALSE ) { perror( "nw_del_folder" ); goto out; } } fprintf( stderr, "done\n" ); if ( nw_parse_directory( dev ) == NULL ) { if ( errno && errno != ENOENT ) { perror( "parsing directory" ); goto out; } } else { fprintf( stderr, "expecting directory to be empty at this point\n" ); goto out; } fprintf( stderr, "FOLDER TESTS\n" ); test = nw_add_folder( dev, "TEST", 1 ); if ( test == 1 ) { fprintf( stderr, " added folder at position %d\n", test ); } else { perror( " first folder not added at position 1" ); goto out; } if ( nw_get_folder( dev, "TEST", 1 ) != test ) { perror( "nw_get_folder failed" ); } test2 = nw_add_folder( dev, "TEST2", 0 ); if ( test2 == 2 ) { fprintf( stderr, " added folder 2 at position %d\n", test2 ); } else { perror( " second folder not added at position 2" ); goto out; } test = nw_del_folder( dev, test ); if ( !test ) { perror( " deleting first folder" ); goto out; } else { fprintf( stderr, " deleted first folder\n" ); } test = nw_add_folder( dev, "TEST", 0 ); if ( test != 2 ) { perror( " first folder not re-added at position 2" ); goto out; } else { fprintf( stderr, " first folder re-added at position %d\n", test ); } test = nw_mv_folder( dev, test, 1 ); if ( test != 1 ) { perror( " moving first folder" ); goto out; } else { fprintf( stderr, " moved first folder to position %d\n", test ); } if ( nw_get_folder( dev, "TEST", 1 ) != 1 ) { perror( " folder not where I expected" ); goto out; } test = nw_ren_folder( dev, test, "TEST3" ); if ( test != 1 ) { perror( " renaming folder" ); goto out; } else { fprintf( stderr, " renamed TEST folder to TEST3\n" ); } /* end of folder tests; now let's test some files */ fprintf( stderr, "\nTRACK TESTS\n" ); test2 = nw_add_track( dev, testfile, NULL, 0, 0 ); if ( test2 == 0 ) { perror( "adding track failed" ); goto out; } else { fprintf( stderr, " added %s to device as track %d\n", testfile, test2 ); } /* pull the metadata */ /* obviously these depend on a very specific test track! */ if (( tptr = nw_get_track_ptr( dev, test2 )) == NULL ) { perror( "fetching track pointer" ); goto out; } if ( nw_track_size( tptr ) != test_file_size ) { fprintf( stderr, " *** size mismatch (%u != %u)\n", nw_track_size( tptr ), test_file_size ); } if ( nw_track_time( tptr ) != test_file_ms ) { fprintf( stderr, " *** time mismatch (%u != %u)\n", nw_track_time( tptr ), test_file_ms ); } if ( nw_track_frames( tptr ) != test_file_frames ) { fprintf( stderr, " *** frames mismatch (%u != %u)\n", nw_track_frames( tptr ), test_file_frames ); } /* fixme check metadata */ fprintf( stderr, " verified file transfer\n" ); test2 = nw_del_track( dev, test2 ); if ( test2 == FALSE ) { perror( " deleting track" ); goto out; } else { fprintf( stderr, " deleted track\n" ); } test2 = nw_add_track( dev, testfile, NULL, 0, 0 ); if ( test2 == 0 ) { perror( " re-adding track" ); goto out; } else { fprintf( stderr, " added %s to device as track %d\n", testfile, test2 ); } /* give the second track some slightly different metadata to differentiate it */ track = nw_get_metadata_NAME( testfile ); filename = nw_get_tag( track, NW_FILENAME ); if ( track == NULL ) { perror( "getting metadata" ); goto out; } else { id3_utf8_t *title = nw_get_tag( track, ID3_FRAME_TITLE ); id3_utf8_t *artist = nw_get_tag( track, ID3_FRAME_ARTIST ); fprintf( stderr, "file: %s\ntitle: %s\n artist: %s\n", filename, title, artist ); g_free( title ); g_free( artist ); } filename[1] = 'a'; nw_set_tag( track, NW_FILENAME, filename ); test2 = nw_add_track( dev, testfile, track, 0, 0 ); g_free( filename ); filename = NULL; if ( test2 == 0 ) { perror( " re-adding track" ); goto out; } else { fprintf( stderr, " added %s to device as track %d\n", testfile, test2 ); } /* swap the tracks around */ fprintf( stderr, " swapping tracks\n" ); test2 = nw_mv_track( dev, test2, 0, 1 ); if ( test2 == 0 ) { perror( " moving track" ); goto out; } else { fprintf( stderr, " moved track 2 to position %d in its own folder\n", test2 ); } fprintf( stderr, " moving track to other folder\n" ); test2 = nw_mv_track( dev, 1, 2, 0 ); if ( test2 == 0 ) { perror( " moving track" ); goto out; } else { fprintf( stderr, " moved track to other folder\n" ); } /* now overwrite the metadata on track 1 so that it matches track 1 */ test2 = nw_ren_track( dev, 1, track ); if ( test2 == 0 ) { perror( " renaming track" ); goto out; } else { fprintf( stderr, " renamed track\n" ); } /* filesystem interface */ fprintf( stderr, "\nFILESYSTEM TESTS\n" ); if ( nw_stat( dev, 1, &statbuf ) == -1 ) { perror( " stat" ); goto out; } else { fprintf( stderr, " file stat ok, file size is %ld\n", statbuf.st_size ); } mfp = nw_fopen( dev, 0, 1, NULL, "rb" ); if ( mfp != NULL ) { fprintf( stderr, " file open ok\n" ); } else { perror( " file open" ); goto out; } /* fixme: verify _CUR and _END as well */ offset = nw_fseek( mfp, 10, SEEK_SET ); if ( offset == -1 ) { perror( " file seek" ); goto out; } else { fprintf( stderr, " file seek ok\n" ); } if ( nw_ftell( mfp ) != 10 ) { if ( errno ) { perror( " file tell" ); } else { fprintf( stderr, " file pointer not at %ld\n", offset ); } goto out; } else { fprintf( stderr, " file tell ok\n" ); } /* push the pointer back to 0 */ offset = nw_fseek( mfp, 0, SEEK_SET ); if ( offset == -1 ) { perror( " file seek" ); goto out; } else { fprintf( stderr, " file seek ok\n" ); } if (( tptr = nw_get_track_ptr( dev, 1 )) == NULL ) { perror( " failed to get tptr" ); goto out; } if (( fp = fopen( "retrieved.mp3", "wb" )) != NULL ) { } else { perror( " copying" ); goto out; } buffer = g_malloc0( ID3_TAG_QUERYSIZE ); nbytes = nw_fread( buffer, 1, ID3_TAG_QUERYSIZE, mfp ); if ( nbytes != ID3_TAG_QUERYSIZE ) { fprintf( stderr, " failed to get id3 header: %s\n", strerror( errno )); goto out; } taglen = id3_tag_query( (guint8 *)buffer, ID3_TAG_QUERYSIZE ); if ( taglen ) { size_t total = 0; buffer = g_realloc( buffer, taglen ); errno = 0; nbytes = nw_fread( &buffer[ID3_TAG_QUERYSIZE], taglen - ID3_TAG_QUERYSIZE, 1, mfp ); if ( nbytes != taglen - ID3_TAG_QUERYSIZE ) { if ( errno ) { perror( " file read" ); } else { fprintf( stderr, " file read got %d, expected %ld\n", nbytes, taglen ); } goto out; } else { fprintf( stderr, " file read (id3 data) ok\n" ); total = taglen; } fwrite( buffer, taglen, 1, fp ); while( total < statbuf.st_size ) { size_t wanted = MIN( taglen, statbuf.st_size - total ); errno = 0; nbytes = nw_fread( buffer, 1, wanted, mfp ); total += nbytes; if ( nbytes != wanted ) { if ( errno ) { perror( " file read" ); } else { fprintf( stderr, " file read got %d, expected %d\n", nbytes, wanted ); fprintf( stderr, " short read: got %d of %ld\n", total, statbuf.st_size ); } goto out; } else { if ( getenv( "EMACS" ) == NULL ) { progress( (double)total / (double)statbuf.st_size, NULL ); } } fwrite( buffer, taglen, 1, fp ); } } else { fprintf( stderr, " no tag found\n" ); goto out; } fclose( fp ); fp = NULL; fprintf( stderr, "\n" ); nw_fclose( mfp ); /* file write tests */ mfp = nw_fopen( dev, 2, 0, "testwrite.mp3", "wb" ); if ( mfp != NULL ) { fprintf( stderr, " file open (write) ok\n" ); } else { perror( " file open (write)" ); goto out; } if (( fp = fopen( testfile, "rb" )) == NULL ) { perror( " fopen" ); goto out; } buffer = g_realloc( buffer, 1024 ); while(( nbytes = fread( buffer, 1, 1024, fp )) > 0 ) { int written = nw_fwrite( buffer, 1, nbytes, mfp ); if ( written != nbytes ) { fprintf( stderr, "write mismatch: got %d, expected %d\n", written, nbytes ); } } nw_fclose( mfp ); mfp = NULL; fprintf( stderr, "completed all tests successfully\n" ); retval = 0; out: /* Clean up after ourselves! */ unlink( "retrieved.mp3" ); if ( track != NULL ) { nw_track_free( track ); } if ( buffer != NULL ) { g_free( buffer ); } if ( fp != NULL ) { fclose( fp ); } if ( mfp != NULL ) { nw_fclose( mfp ); } if ( testdev != NULL ) { g_free( testdev ); } if ( testfile != NULL ) { g_free( testfile ); } if ( dev != NULL ) { nw_dev_free( dev ); } exit( retval ); }