Added simple unit tests and expected output
parent
6c389a708b
commit
fe6ee8bc05
@ -0,0 +1,48 @@
|
||||
#include "makernote.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
void testMatch(const std::string& reg, const std::string& key);
|
||||
|
||||
int main()
|
||||
{
|
||||
testMatch("Canon", "Canon");
|
||||
testMatch("Canon*", "Canon");
|
||||
testMatch("Canon*", "Canon Corp.");
|
||||
testMatch("*foo*bar*", "foobar");
|
||||
testMatch("*foo*bar*", "barfoofoobarbar");
|
||||
testMatch("foo*bar", "foo");
|
||||
testMatch("foo*bar", "bar");
|
||||
testMatch("foo*bar", "foobar");
|
||||
testMatch("foo*bar", "fooYAHOObar");
|
||||
testMatch("foo*bar", "Thefoobar");
|
||||
testMatch("foo*bar", "foobarTrick");
|
||||
testMatch("foo*bar", "ThefoobarTrick");
|
||||
testMatch("foo*bar", "ThefooYAHOObarTrick");
|
||||
|
||||
testMatch("*", "anything");
|
||||
testMatch("**", "anything times two");
|
||||
|
||||
testMatch("*bar", "bar");
|
||||
testMatch("b*bar", "bar");
|
||||
testMatch("b*bar", "bbar");
|
||||
testMatch("*foobar", "bar");
|
||||
testMatch("*bar", "foobar");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void testMatch(const std::string& reg, const std::string& key)
|
||||
{
|
||||
std::pair<bool, int> rc = Exif::MakerNoteFactory::match(reg, key);
|
||||
|
||||
if (rc.first) {
|
||||
std::cout << "Key '" << key << "' matches '" << reg << "' in "
|
||||
<< rc.second << " characters.\n";
|
||||
}
|
||||
else {
|
||||
std::cout << "Key '" << key << "' does not match '" << reg << "'.\n";
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
Key 'Canon' matches 'Canon' in 5 characters.
|
||||
Key 'Canon' matches 'Canon*' in 5 characters.
|
||||
Key 'Canon Corp.' matches 'Canon*' in 5 characters.
|
||||
Key 'foobar' matches '*foo*bar*' in 6 characters.
|
||||
Key 'barfoofoobarbar' matches '*foo*bar*' in 6 characters.
|
||||
Key 'foo' does not match 'foo*bar'.
|
||||
Key 'bar' does not match 'foo*bar'.
|
||||
Key 'foobar' matches 'foo*bar' in 6 characters.
|
||||
Key 'fooYAHOObar' matches 'foo*bar' in 6 characters.
|
||||
Key 'Thefoobar' does not match 'foo*bar'.
|
||||
Key 'foobarTrick' does not match 'foo*bar'.
|
||||
Key 'ThefoobarTrick' does not match 'foo*bar'.
|
||||
Key 'ThefooYAHOObarTrick' does not match 'foo*bar'.
|
||||
Key 'anything' matches '*' in 0 characters.
|
||||
Key 'anything times two' matches '**' in 0 characters.
|
||||
Key 'bar' matches '*bar' in 3 characters.
|
||||
Key 'bar' does not match 'b*bar'.
|
||||
Key 'bbar' matches 'b*bar' in 4 characters.
|
||||
Key 'bar' does not match '*foobar'.
|
||||
Key 'foobar' matches '*bar' in 3 characters.
|
@ -0,0 +1,232 @@
|
||||
// ***************************************************************** -*- C++ -*-
|
||||
/*
|
||||
Abstract : ExifData write unit tests
|
||||
|
||||
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
||||
Version : $Name: $ $Revision: 1.1 $
|
||||
|
||||
Test procedure:
|
||||
$ rm -f test.jpg thumb.jpg iii ttt;
|
||||
$ ./exifprint ../test/img_1771.jpg > iii;
|
||||
$ cp ../test/img_1771.jpg ./test.jpg;
|
||||
$ ./makernote-test2 ../test/img_1771.jpg > ttt;
|
||||
$ diff iii ttt
|
||||
|
||||
*/
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#include "exif.hpp"
|
||||
#include "makernote.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
// *****************************************************************************
|
||||
// local declarations
|
||||
|
||||
using namespace Exif;
|
||||
|
||||
void testCase(const std::string& file1,
|
||||
const std::string& file2,
|
||||
const std::string& thumb,
|
||||
const std::string& key,
|
||||
const std::string& value);
|
||||
void exifPrint(const ExifData& exifData);
|
||||
std::string readError(int rc, const char* file);
|
||||
std::string writeError(int rc, const char* file);
|
||||
|
||||
// *****************************************************************************
|
||||
// Main
|
||||
int main(int argc, char* const argv[])
|
||||
try {
|
||||
|
||||
if (argc != 3) {
|
||||
std::cout << "Usage: write-test file case\n\n"
|
||||
<< "where case is an integer between 1 and 6\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string testFile = argv[1];
|
||||
std::istringstream iss(argv[2]);
|
||||
int testNo;
|
||||
iss >> testNo;
|
||||
|
||||
int rc = 0;
|
||||
switch (testNo) {
|
||||
case 1:
|
||||
std::cerr << "Case 1: ";
|
||||
std::cerr << "Non-intrusive change to the standard Exif metadata\n";
|
||||
testCase(testFile, "test1.jpg", "thumb1",
|
||||
"Image.DateTime.DateTimeOriginal",
|
||||
"1999:11:22 00:11:22");
|
||||
break;
|
||||
case 2:
|
||||
std::cerr << "Case 2: ";
|
||||
std::cerr << "Non-intrusive change to the makernote metadata\n";
|
||||
testCase(testFile, "test2.jpg", "thumb2",
|
||||
"Makernote.Canon.OwnerName",
|
||||
"Chan YeeSend");
|
||||
break;
|
||||
case 3:
|
||||
std::cerr << "Case 3: ";
|
||||
std::cerr << "Non-intrusive change to the Exif metadata (w/o makernote)\n";
|
||||
testCase(testFile, "test3.jpg", "thumb3",
|
||||
"Image.DateTime.DateTimeOriginal",
|
||||
"1999:11:22 00:11:22");
|
||||
break;
|
||||
case 4:
|
||||
std::cerr << "Case 4: ";
|
||||
std::cerr << "Intrusive change to the standard Exif metadata\n";
|
||||
testCase(testFile, "test4.jpg", "thumb4",
|
||||
"Image.DateTime.DateTimeOriginal",
|
||||
"1999:11:22 00:11:22 and twenty seconds");
|
||||
break;
|
||||
case 5:
|
||||
std::cerr << "Case 5: ";
|
||||
std::cerr << "Intrusive change to the makernote metadata\n";
|
||||
testCase(testFile, "test5.jpg", "thumb5",
|
||||
"Makernote.Canon.OwnerName",
|
||||
"Frau Chan YeeSend und Herr Andreas Huggel");
|
||||
break;
|
||||
case 6:
|
||||
std::cerr << "Case 6: ";
|
||||
std::cerr << "Intrusive change to the Exif metadata (w/o makernote)\n";
|
||||
testCase(testFile, "test6.jpg", "thumb6",
|
||||
"Image.DateTime.DateTimeOriginal",
|
||||
"1999:11:22 00:11:22 and twenty seconds");
|
||||
break;
|
||||
default:
|
||||
std::cout << "Usage: exiftest file case\n\n"
|
||||
<< "where case is an integer between 1 and 6\n";
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
catch (Error& e) {
|
||||
std::cerr << "Caught Exif exception '" << e << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
void testCase(const std::string& file1,
|
||||
const std::string& file2,
|
||||
const std::string& thumb,
|
||||
const std::string& key,
|
||||
const std::string& value)
|
||||
{
|
||||
ExifData ed1;
|
||||
|
||||
std::cerr << "---> Reading file " << file1 << "\n";
|
||||
int rc = ed1.read(file1);
|
||||
if (rc) {
|
||||
std::string error = readError(rc, file1.c_str());
|
||||
throw Error(error);
|
||||
}
|
||||
|
||||
std::cerr << "---> Modifying Exif data\n";
|
||||
Exif::ExifData::iterator pos = ed1.findKey(key);
|
||||
if (pos == ed1.end()) {
|
||||
throw Error("Metadatum with key = " + key + " not found");
|
||||
}
|
||||
pos->setValue(value);
|
||||
|
||||
std::cerr << "---> Writing Exif data to file " << file2 << "\n";
|
||||
rc = ed1.write(file2);
|
||||
if (rc) {
|
||||
std::string error = writeError(rc, file2.c_str());
|
||||
throw Error(error);
|
||||
}
|
||||
|
||||
ExifData ed2;
|
||||
|
||||
std::cerr << "---> Reading file " << file2 << "\n";
|
||||
rc = ed2.read(file2);
|
||||
if (rc) {
|
||||
std::string error = readError(rc, file2.c_str());
|
||||
throw Error(error);
|
||||
}
|
||||
|
||||
exifPrint(ed2);
|
||||
|
||||
std::cerr << "---> Writing Exif thumbnail to file " << thumb << ".*\n";
|
||||
ed2.writeThumbnail(thumb);
|
||||
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void exifPrint(const ExifData& exifData)
|
||||
{
|
||||
ExifData::const_iterator i = exifData.begin();
|
||||
for (; i != exifData.end(); ++i) {
|
||||
std::cout << std::setw(53) << std::setfill(' ') << std::left
|
||||
<< i->key() << " "
|
||||
<< "0x" << std::setw(4) << std::setfill('0') << std::right
|
||||
<< std::hex << i->tag() << " "
|
||||
<< std::dec << i->value()
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::string readError(int rc, const char* file)
|
||||
{
|
||||
std::string error;
|
||||
switch (rc) {
|
||||
case -1:
|
||||
error = "Couldn't open file `" + std::string(file) + "'";
|
||||
break;
|
||||
case 1:
|
||||
error = "Couldn't read from the input stream";
|
||||
break;
|
||||
case 2:
|
||||
error = "This does not look like a JPEG image";
|
||||
break;
|
||||
case 3:
|
||||
error = "No Exif data found in the file";
|
||||
break;
|
||||
case -99:
|
||||
error = "Unsupported Exif or GPS data found in IFD 1";
|
||||
break;
|
||||
default:
|
||||
error = "Reading Exif data failed, rc = " + toString(rc);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
std::string writeError(int rc, const char* file)
|
||||
{
|
||||
std::string error;
|
||||
switch (rc) {
|
||||
case -1:
|
||||
error = "Couldn't open file `" + std::string(file) + "'";
|
||||
break;
|
||||
case -2:
|
||||
error = "Couldn't open temporary file";
|
||||
break;
|
||||
case -3:
|
||||
error = "Renaming temporary file failed";
|
||||
break;
|
||||
case 1:
|
||||
error = "Couldn't read from the input stream";
|
||||
break;
|
||||
case 2:
|
||||
error = "This does not look like a JPEG image";
|
||||
break;
|
||||
case 3:
|
||||
error = "No JFIF APP0 or Exif APP1 segment found in the file";
|
||||
break;
|
||||
case 4:
|
||||
error = "Writing to the output stream failed";
|
||||
break;
|
||||
default:
|
||||
error = "Reading Exif data failed, rc = " + toString(rc);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
------------------------------------------------------------
|
||||
Case 1: Non-intrusive change to the standard Exif metadata
|
||||
---> Reading file ../test/img_1771.jpg
|
||||
---> Modifying Exif data
|
||||
---> Writing Exif data to file test1.jpg
|
||||
->>>>>> using non-intrusive writing <<<<<<-
|
||||
---> Reading file test1.jpg
|
||||
---> Writing Exif thumbnail to file thumb1.*
|
||||
13c13
|
||||
< Image.DateTime.DateTimeOriginal 0x9003 2003:12:14 12:01:44
|
||||
---
|
||||
> Image.DateTime.DateTimeOriginal 0x9003 1999:11:22 00:11:22
|
||||
------------------------------------------------------------
|
||||
Case 2: Non-intrusive change to the makernote metadata
|
||||
---> Reading file ../test/img_1771.jpg
|
||||
---> Modifying Exif data
|
||||
---> Writing Exif data to file test2.jpg
|
||||
->>>>>> using non-intrusive writing <<<<<<-
|
||||
---> Reading file test2.jpg
|
||||
---> Writing Exif thumbnail to file thumb2.*
|
||||
49c49
|
||||
< Makernote.Canon.OwnerName 0x0009 Andreas Huggel
|
||||
---
|
||||
> Makernote.Canon.OwnerName 0x0009 Chan YeeSend
|
||||
------------------------------------------------------------
|
||||
Case 3: Non-intrusive change to the Exif metadata (w/o makernote)
|
||||
---> Reading file ../test/kodak-dc210.jpg
|
||||
---> Modifying Exif data
|
||||
---> Writing Exif data to file test3.jpg
|
||||
->>>>>> using non-intrusive writing <<<<<<-
|
||||
---> Reading file test3.jpg
|
||||
---> Writing Exif thumbnail to file thumb3.*
|
||||
14c14
|
||||
< Image.DateTime.DateTimeOriginal 0x9003 2000:10:26 16:46:51
|
||||
---
|
||||
> Image.DateTime.DateTimeOriginal 0x9003 1999:11:22 00:11:22
|
||||
------------------------------------------------------------
|
||||
Case 4: Intrusive change to the standard Exif metadata
|
||||
---> Reading file ../test/img_1771.jpg
|
||||
---> Modifying Exif data
|
||||
---> Writing Exif data to file test4.jpg
|
||||
->>>>>> writing from metadata <<<<<<-
|
||||
---> Reading file test4.jpg
|
||||
---> Writing Exif thumbnail to file thumb4.*
|
||||
9c9
|
||||
< Image.ExifFormat.ExifTag 0x8769 196
|
||||
---
|
||||
> Image.ExifFormat.ExifTag 0x8769 184
|
||||
13c13
|
||||
< Image.DateTime.DateTimeOriginal 0x9003 2003:12:14 12:01:44
|
||||
---
|
||||
> Image.DateTime.DateTimeOriginal 0x9003 1999:11:22 00:11:22 and twenty seconds
|
||||
29c29
|
||||
< Image.ExifFormat.InteroperabilityTag 0xa005 1416
|
||||
---
|
||||
> Image.ExifFormat.InteroperabilityTag 0xa005 1423
|
||||
60c60
|
||||
< Thumbnail.RecordingOffset.JPEGInterchangeFormat 0x0201 2036
|
||||
---
|
||||
> Thumbnail.RecordingOffset.JPEGInterchangeFormat 0x0201 1571
|
||||
------------------------------------------------------------
|
||||
Case 5: Intrusive change to the makernote metadata
|
||||
---> Reading file ../test/img_1771.jpg
|
||||
---> Modifying Exif data
|
||||
---> Writing Exif data to file test5.jpg
|
||||
->>>>>> writing from metadata <<<<<<-
|
||||
---> Reading file test5.jpg
|
||||
---> Writing Exif thumbnail to file thumb5.*
|
||||
9c9
|
||||
< Image.ExifFormat.ExifTag 0x8769 196
|
||||
---
|
||||
> Image.ExifFormat.ExifTag 0x8769 184
|
||||
29c29
|
||||
< Image.ExifFormat.InteroperabilityTag 0xa005 1416
|
||||
---
|
||||
> Image.ExifFormat.InteroperabilityTag 0xa005 1414
|
||||
49c49
|
||||
< Makernote.Canon.OwnerName 0x0009 Andreas Huggel
|
||||
---
|
||||
> Makernote.Canon.OwnerName 0x0009 Frau Chan YeeSend und Herr Andreas Huggel
|
||||
60c60
|
||||
< Thumbnail.RecordingOffset.JPEGInterchangeFormat 0x0201 2036
|
||||
---
|
||||
> Thumbnail.RecordingOffset.JPEGInterchangeFormat 0x0201 1562
|
||||
------------------------------------------------------------
|
||||
Case 6: Intrusive change to the Exif metadata (w/o makernote)
|
||||
---> Reading file ../test/kodak-dc210.jpg
|
||||
---> Modifying Exif data
|
||||
---> Writing Exif data to file test6.jpg
|
||||
->>>>>> writing from metadata <<<<<<-
|
||||
---> Reading file test6.jpg
|
||||
---> Writing Exif thumbnail to file thumb6.*
|
||||
10c10
|
||||
< Image.ExifFormat.ExifTag 0x8769 374
|
||||
---
|
||||
> Image.ExifFormat.ExifTag 0x8769 192
|
||||
14c14
|
||||
< Image.DateTime.DateTimeOriginal 0x9003 2000:10:26 16:46:51
|
||||
---
|
||||
> Image.DateTime.DateTimeOriginal 0x9003 1999:11:22 00:11:22 and twenty seconds
|
||||
33c33
|
||||
< Thumbnail.RecordingOffset.StripOffsets 0x0111 928
|
||||
---
|
||||
> Thumbnail.RecordingOffset.StripOffsets 0x0111 765
|
@ -0,0 +1,62 @@
|
||||
#! /bin/sh
|
||||
# Test driver for the write unit tests
|
||||
|
||||
# Case 1
|
||||
echo "------------------------------------------------------------"
|
||||
testFile="../test/img_1771.jpg"
|
||||
rm -f test1.jpg thumb1.jpg
|
||||
rm -f iii ttt;
|
||||
./exifprint $testFile > iii;
|
||||
cp $testFile ./test1.jpg;
|
||||
./write-test $testFile 1 > ttt;
|
||||
diff iii ttt
|
||||
|
||||
# Case 2
|
||||
echo "------------------------------------------------------------"
|
||||
testFile="../test/img_1771.jpg"
|
||||
rm -f test2.jpg thumb2.jpg
|
||||
rm -f iii ttt;
|
||||
./exifprint $testFile > iii;
|
||||
cp $testFile ./test2.jpg;
|
||||
./write-test $testFile 2 > ttt;
|
||||
diff iii ttt
|
||||
|
||||
# Case 3
|
||||
echo "------------------------------------------------------------"
|
||||
testFile="../test/kodak-dc210.jpg"
|
||||
rm -f test3.jpg thumb3.jpg
|
||||
rm -f iii ttt;
|
||||
./exifprint $testFile > iii;
|
||||
cp $testFile ./test3.jpg;
|
||||
./write-test $testFile 3 > ttt;
|
||||
diff iii ttt
|
||||
|
||||
# Case 4
|
||||
echo "------------------------------------------------------------"
|
||||
testFile="../test/img_1771.jpg"
|
||||
rm -f test4.jpg thumb4.jpg
|
||||
rm -f iii ttt;
|
||||
./exifprint $testFile > iii;
|
||||
cp $testFile ./test4.jpg;
|
||||
./write-test $testFile 4 > ttt;
|
||||
diff iii ttt
|
||||
|
||||
# Case 5
|
||||
echo "------------------------------------------------------------"
|
||||
testFile="../test/img_1771.jpg"
|
||||
rm -f test5.jpg thumb5.jpg
|
||||
rm -f iii ttt;
|
||||
./exifprint $testFile > iii;
|
||||
cp $testFile ./test5.jpg;
|
||||
./write-test $testFile 5 > ttt;
|
||||
diff iii ttt
|
||||
|
||||
# Case 6
|
||||
echo "------------------------------------------------------------"
|
||||
testFile="../test/kodak-dc210.jpg"
|
||||
rm -f test6.jpg thumb6.jpg
|
||||
rm -f iii ttt;
|
||||
./exifprint $testFile > iii;
|
||||
cp $testFile ./test6.jpg;
|
||||
./write-test $testFile 6 > ttt;
|
||||
diff iii ttt
|
Loading…
Reference in New Issue