#include <ctype.h>
#include <fcntl.h>
#include <map>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <vector>
#include <fs_attr.h>
#include <fs_info.h>
#include <Application.h>
#include <Bitmap.h>
#include <DataIO.h>
#include <Drivers.h>
#include <Message.h>
#include <Mime.h>
#if !TEST_R5
#include <mime/database_support.h>
#endif
#include <Path.h>
#include <StorageKit.h>
#include <String.h>
#include <storage_support.h>
#include "TestShell.h"
#include "TestApp.h"
#include "TestUtils.h"
#include "MimeTypeTest.h"
static const char *testDir = "/tmp/mimeTestDir";
static const char *R5DatabaseDir = "/boot/home/config/settings/beos_mime";
#if TEST_R5
static std::string mimeDatabaseDir = R5DatabaseDir;
#else
static std::string mimeDatabaseDir = BPrivate::Storage::Mime::kDatabaseDir;
#endif
static const char *testType = "text/x-vnd.obos-Storage-Kit-Test";
static const char *testType1 = "text/x-vnd.obos-Storage-Kit-Test1";
static const char *testType2 = "text/x-vnd.obos-Storage-Kit-Test2";
static const char *testType3 = "text/x-vnd.obos-Storage-Kit-Test3";
static const char *testType4 = "text/x-vnd.obos-Storage-Kit-Test4";
static const char *testType5 = "text/x-vnd.obos-Storage-Kit-Test5";
static const char *testTypeApp = "application/StorageKit-Test";
static const char *testTypeApp1 = "application/"
"x-vnd.obos.mime.test.test1";
static const char *testTypeApp2 = "application/"
"x-vnd.obos.mime.test.test2";
static const char *testTypeApp3 = "application/"
"x-vnd.obos.mime.test.test3";
static const char *testTypeInvalid = "text/Are spaces valid?";
static const char *testTypeSuperValid = "valid-but-fake-supertype";
static const char *testTypeSuperInvalid = "?????";
static const char *wildcardType = "application/octet-stream";
static const char *applicationSupertype = "application";
static const char *testApp = "/boot/beos/apps/SoundRecorder";
static const char *testApp2 = "/boot/beos/apps/CDPlayer";
static const char *fakeTestApp = "/__this_isn't_likely_to_exist__";
static const char *applicationsField = "applications";
static const char *typeField = "type";
static const char *typesField = "types";
static const char *fileExtField = "extensions";
static const char *attrInfoField_Name = "attr:name";
static const char *attrInfoField_PublicName = "attr:public_name";
static const char *attrInfoField_Type = "attr:type";
static const char *attrInfoField_Viewable = "attr:viewable";
static const char *attrInfoField_Editable = "attr:editable";
static const char *testDescr = "Just a test, nothing more :-)";
static const char *testDescr2 = "Another amazing test string";
static const char *longDescr =
"This description is longer than B_MIME_TYPE_LENGTH, which is quite useful for certain things... "
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
static const char *testSig = "application/x-vnd.obos.mime-type-test";
static const char *testSig2 = "application/x-vnd.obos.mime-type-test-2";
static const char *longSig = "application/x-vnd.obos.mime-type-test-long."
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
static bool operator==(BBitmap &bmp1, BBitmap &bmp2);
static bool operator!=(BBitmap &bmp1, BBitmap &bmp2);
static bool operator==(BMessage &msg1, BMessage &msg2);
static bool operator!=(BMessage &msg1, BMessage &msg2);
static void fill_bitmap(BBitmap &bmp, char value);
#if !TEST_R5
static status_t reduce_color_depth(BBitmap &src32, BBitmap &dest8);
#endif
static void to_lower(const char *str, std::string &result);
static std::string to_lower(const char *str);
static void remove_type(const char *type, const char *databaseDir = mimeDatabaseDir.c_str());
static bool type_exists(const char *type, const char *databaseDir = mimeDatabaseDir.c_str());
class ContainerAdapter;
class SetAdapter;
class QueueAdapter;
void FillWithMimeTypes(ContainerAdapter &container, BMessage &typeMessage, const char* fieldName);
class MimeTypeTestSuite : public CppUnit::TestSuite {
public:
MimeTypeTestSuite() : CppUnit::TestSuite(), fMimeDirExisted(false) {}
virtual void setUp()
{
if (mimeDatabaseDir != R5DatabaseDir) {
BEntry dir(mimeDatabaseDir.c_str());
if (dir.InitCheck() != B_OK || !dir.Exists()) {
if (BTestShell::GlobalBeVerbose())
cout << "(Making a copy of your MIME database at '" + mimeDatabaseDir + "')" << endl;
std::string cmd = std::string("copyattr -d -r -- ") + R5DatabaseDir
+ " " + mimeDatabaseDir;
ExecCommand(cmd.c_str());
} else {
fMimeDirExisted = true;
if (BTestShell::GlobalBeVerbose())
cout << "(Using existing copy of MIME database in '" + mimeDatabaseDir + "')" << endl;
}
}
}
virtual void tearDown()
{
if (mimeDatabaseDir != R5DatabaseDir && !fMimeDirExisted) {
if (BTestShell::GlobalBeVerbose())
cout << "(Removing copy of MIME database in '" + mimeDatabaseDir + "')" << endl;
std::string cmd = std::string("rm -rf ") + mimeDatabaseDir;
ExecCommand(cmd.c_str());
}
}
virtual void run( CppUnit::TestResult *result )
{
setUp();
CppUnit::TestSuite::run(result);
tearDown();
}
private:
bool fMimeDirExisted;
};
CppUnit::Test*
MimeTypeTest::Suite() {
MimeTypeTestSuite *suite = new MimeTypeTestSuite();
typedef CppUnit::TestCaller<MimeTypeTest> TC;
suite->addTest( new TC("BMimeType::Install/Delete Test",
&MimeTypeTest::InstallDeleteTest) );
suite->addTest( new TC("BMimeType::App Hint Test",
&MimeTypeTest::AppHintTest) );
suite->addTest( new TC("BMimeType::Attribute Info Test",
&MimeTypeTest::AttrInfoTest) );
suite->addTest( new TC("BMimeType::Long Description Test",
&MimeTypeTest::LongDescriptionTest) );
suite->addTest( new TC("BMimeType::Short Description Test",
&MimeTypeTest::ShortDescriptionTest) );
suite->addTest( new TC("BMimeType::File Extensions Test",
&MimeTypeTest::FileExtensionsTest) );
suite->addTest( new TC("BMimeType::Icon Test (Large)",
&MimeTypeTest::LargeIconTest) );
suite->addTest( new TC("BMimeType::Icon Test (Mini)",
&MimeTypeTest::MiniIconTest) );
suite->addTest( new TC("BMimeType::Icon For Type Test (Large)",
&MimeTypeTest::LargeIconForTypeTest) );
suite->addTest( new TC("BMimeType::Icon For Type Test (Mini)",
&MimeTypeTest::MiniIconForTypeTest) );
suite->addTest( new TC("BMimeType::Installed Types Test",
&MimeTypeTest::InstalledTypesTest) );
suite->addTest( new TC("BMimeType::Preferred App Test",
&MimeTypeTest::PreferredAppTest) );
suite->addTest( new TC("BMimeType::Supporting Apps Test",
&MimeTypeTest::SupportingAppsTest) );
suite->addTest( new TC("BMimeType::Supported Types Test",
&MimeTypeTest::SupportedTypesTest) );
suite->addTest( new TC("BMimeType::Wildcard Apps Test",
&MimeTypeTest::WildcardAppsTest) );
suite->addTest( new TC("BMimeType::Initialization Test",
&MimeTypeTest::InitTest) );
suite->addTest( new TC("BMimeType::MIME String Test",
&MimeTypeTest::StringTest) );
suite->addTest( new TC("BMimeType::MIME Monitoring Test",
&MimeTypeTest::MonitoringTest) );
suite->addTest( new TC("BMimeType::update_mime_info() Test",
&MimeTypeTest::UpdateMimeInfoTest) );
suite->addTest( new TC("BMimeType::create_app_meta_mime() Test",
&MimeTypeTest::CreateAppMetaMimeTest) );
suite->addTest( new TC("BMimeType::get_device_icon() Test",
&MimeTypeTest::GetDeviceIconTest) );
suite->addTest( new TC("BMimeType::Sniffer Rule Test",
&MimeTypeTest::SnifferRuleTest) );
suite->addTest( new TC("BMimeType::Sniffing Test",
&MimeTypeTest::SniffingTest) );
return suite;
}
bool
operator==(BBitmap &bmp1, BBitmap &bmp2) {
if (bmp1.Bounds() == bmp2.Bounds()) {
if (bmp1.ColorSpace() == bmp2.ColorSpace()) {
char *data1 = (char*)bmp1.Bits();
char *data2 = (char*)bmp2.Bits();
for (int i = 0; i < bmp1.BitsLength(); data1++, data2++, i++) {
if (*data1 != *data2) {
return false;
}
}
return true;
} else
return false;
} else
return false;
}
bool
operator!=(BBitmap &bmp1, BBitmap &bmp2) {
return !(bmp1 == bmp2);
}
bool
operator==(BMessage &msg1, BMessage &msg2) {
status_t err = B_OK;
if (msg1.what != msg2.what)
return false;
int count1, count2;
count1 = msg1.CountNames(B_ANY_TYPE);
count2 = msg2.CountNames(B_ANY_TYPE);
if (count1 != count2 && (count1 == 0 || count2 == 0))
return false;
for (int i = 0; i < count1 && !err; i++) {
char *name;
type_code typeFound1, typeFound2;
int32 countFound1, countFound2;
err = msg1.GetInfo(B_ANY_TYPE, i, &name, &typeFound1, &countFound1);
if (!err)
err = msg2.GetInfo(name, &typeFound2, &countFound2);
if (!err)
err = (typeFound1 == typeFound2 && countFound1 == countFound2 ? B_OK : B_ERROR);
if (!err) {
for (int j = 0; j < countFound1; j++) {
void *data1, *data2;
ssize_t bytes1, bytes2;
err = msg1.FindData(name, typeFound1, j, (const void**)&data1, &bytes1);
if (!err)
err = msg2.FindData(name, typeFound2, j, (const void**)&data2, &bytes2);
if (!err)
err = (bytes1 == bytes2 && memcmp(data1, data2, bytes1) == 0 ? B_OK : B_ERROR);
}
}
}
return !err;
}
bool
operator!=(BMessage &msg1, BMessage &msg2) {
return !(msg1 == msg2);
}
void
fill_bitmap(BBitmap &bmp, char value) {
char *data = (char*)bmp.Bits();
for (int i = 0; i < bmp.BitsLength(); data++, i++) {
*data = value;
}
}
void
fill_bitmap32(BBitmap &bmp, char r, char g, char b, char a) {
if (bmp.ColorSpace() == B_RGB32 || bmp.ColorSpace() == B_RGBA32) {
char *data = (char*)bmp.Bits();
for (int i = 0; i+3 < bmp.BitsLength(); data += 4, i+= 4) {
data[0] = b;
data[1] = g;
data[2] = r;
data[3] = a;
}
}
}
#if !TEST_R5
status_t
reduce_color_depth(BBitmap &src32, BBitmap &dest8)
{
status_t err = (src32.ColorSpace() == B_RGB32
&& dest8.ColorSpace() == B_CMAP8
&& src32.InitCheck() == B_OK
&& dest8.InitCheck() == B_OK
&& src32.Bounds() == dest8.Bounds())
? B_OK
: B_BAD_VALUE;
if (!err) {
char *data = (char*)src32.Bits();
for (int32 i = 0; i*4+3 < src32.BitsLength(); data += 4, i++) {
char rgb[3];
rgb[0] = data[2];
rgb[1] = data[1];
rgb[2] = data[0];
dest8.SetBits(rgb, 3, i, B_RGB32);
}
}
return err;
}
#endif
class IconHelper {
public:
IconHelper(icon_size which)
: bmp1(BitmapBounds(which), B_CMAP8),
bmp2(BitmapBounds(which), B_CMAP8),
bmpTemp(BitmapBounds(which), B_CMAP8),
size(which)
{
fill_bitmap(bmp1, 1);
fill_bitmap(bmp2, 2);
fill_bitmap(bmpTemp, 3);
}
virtual ~IconHelper() {}
BRect BitmapBounds(icon_size isize) {
return isize == B_LARGE_ICON ? BRect(0,0,31,31) : BRect(0,0,15,15);
}
BRect BitmapBounds() {
return BitmapBounds(size);
}
virtual status_t GetIcon(BMimeType &mime, BBitmap *icon) {
return mime.GetIcon(icon, size);
}
virtual status_t SetIcon(BMimeType &mime, BBitmap *icon) {
return mime.SetIcon(icon, size);
}
virtual status_t DeleteIcon(BMimeType &mime) {
#if TEST_R5
return B_BAD_VALUE;
#else
return mime.DeleteIcon(size);
#endif
}
BBitmap* TempBitmap() {
return &bmpTemp;
}
BBitmap* Bitmap1() {
return &bmp1;
}
BBitmap* Bitmap2() {
return &bmp2;
}
icon_size Size() {
return size;
}
protected:
BBitmap bmp1;
BBitmap bmp2;
BBitmap bmpTemp;
icon_size size;
};
class IconForTypeHelper : public IconHelper {
public:
IconForTypeHelper(const char *fileType, icon_size which)
: IconHelper(which), fileType(fileType) {}
virtual ~IconForTypeHelper() {}
virtual status_t GetIcon(BMimeType &mime, BBitmap *icon) {
return mime.GetIconForType(fileType.c_str(), icon, size);
}
virtual status_t SetIcon(BMimeType &mime, BBitmap *icon) {
return mime.SetIconForType(fileType.c_str(), icon, size);
}
virtual status_t DeleteIcon(BMimeType &mime) {
#if TEST_R5
return B_BAD_VALUE;
#else
return mime.DeleteIconForType(fileType.c_str(), size);
#endif
}
protected:
std::string fileType;
};
class ContainerAdapter {
public:
virtual void Add(std::string value) = 0;
};
class SetAdapter : public ContainerAdapter {
public:
SetAdapter(std::set<std::string> &set)
: fSet(set) { }
virtual void Add(std::string value) {
fSet.insert(value);
}
protected:
std::set<std::string> &fSet;
};
class QueueAdapter : public ContainerAdapter {
public:
QueueAdapter(std::queue<std::string> &queue)
: fQueue(queue) { }
virtual void Add(std::string value) {
fQueue.push(value);
}
protected:
std::queue<std::string> &fQueue;
};
void
MimeTypeTest::setUp()
{
BasicTest::setUp();
execCommand(string("mkdir ") + testDir);
fApplication = new BTestApp(testSig);
if (fApplication->Init() != B_OK) {
fprintf(stderr, "Failed to initialize application.\n");
delete fApplication;
fApplication = NULL;
}
}
void
MimeTypeTest::tearDown()
{
execCommand(string("rm -rf ") + testDir);
if (fApplication) {
fApplication->Terminate();
delete fApplication;
fApplication = NULL;
}
const char * const testTypes[] = {
testType, testType1, testType2, testType3, testType4, testType5,
testTypeApp, testTypeApp1, testTypeApp2, testTypeApp3,
};
for (uint32 i = 0; i < sizeof(testTypes) / sizeof(const char*); i++) {
BMimeType type(testTypes[i]);
type.Delete();
}
BasicTest::tearDown();
}
void
MimeTypeTest::AppHintTest() {
BEntry entry(testApp);
entry_ref appRef;
CHK(entry.InitCheck() == B_OK);
CHK(entry.GetRef(&appRef) == B_OK);
BEntry entry2(testApp2);
entry_ref appRef2;
CHK(entry2.InitCheck() == B_OK);
CHK(entry2.GetRef(&appRef2) == B_OK);
NextSubTest();
{
BMimeType mime;
entry_ref ref;
CHK(mime.InitCheck() == B_NO_INIT);
CHK(mime.GetAppHint(&ref) != B_OK);
CHK(mime.SetAppHint(&ref) != B_OK);
}
NextSubTest();
{
entry_ref ref;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
#if TEST_R5
CHK(!mime.IsInstalled());
CHK(mime.GetAppHint(NULL) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetAppHint(NULL) != B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAppHint(NULL) != B_OK);
CHK(mime.SetAppHint(NULL) != B_OK);
#else
CHK(!mime.IsInstalled());
CHK(mime.GetAppHint(NULL) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetAppHint(NULL) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetAppHint(&appRef) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAppHint(&ref) == B_OK);
CHK(ref == appRef);
CHK(mime.SetAppHint(NULL) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAppHint(&ref) != B_OK);
#endif
}
NextSubTest();
{
#if !TEST_R5
entry_ref ref;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.DeleteAppHint() != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetAppHint(&appRef) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAppHint(&ref) == B_OK);
CHK(ref == appRef);
CHK(mime.DeleteAppHint() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAppHint(&ref) != B_OK);
#endif
}
NextSubTest();
{
entry_ref ref;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.GetAppHint(&ref) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetAppHint(&appRef) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAppHint(&ref) == B_OK);
CHK(ref == appRef);
}
NextSubTest();
{
entry_ref ref;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAppHint(&ref) == B_ENTRY_NOT_FOUND);
CHK(mime.SetAppHint(&appRef) == B_OK);
CHK(mime.GetAppHint(&ref) == B_OK);
CHK(ref == appRef);
CHK(mime.SetAppHint(&appRef2) == B_OK);
CHK(mime.GetAppHint(&ref) == B_OK);
CHK(ref == appRef2);
CHK(ref != appRef);
}
NextSubTest();
{
entry_ref ref(-1, -1, NULL);
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.SetAppHint(&appRef) == B_OK);
CHK(mime.SetAppHint(&ref) != B_OK);
}
NextSubTest();
{
entry_ref ref(0, 0, "__this_ought_not_exist__");
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.SetAppHint(&appRef) == B_OK);
CHK(mime.SetAppHint(&ref) != B_OK);
}
NextSubTest();
{
entry_ref fakeRef;
entry_ref ref;
BEntry entry(fakeTestApp);
CHK(entry.InitCheck() == B_OK);
CHK(!entry.Exists());
CHK(entry.GetRef(&fakeRef) == B_OK);
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.SetAppHint(&appRef) == B_OK);
CHK(mime.SetAppHint(&fakeRef) == B_OK);
CHK(mime.GetAppHint(&ref) == B_OK);
CHK(ref == fakeRef);
CHK(ref != appRef);
}
}
void
MimeTypeTest::AttrInfoTest() {
const int32 WHAT = 233;
BMessage msg1(WHAT), msg2(WHAT), msg3(WHAT), msgIncomplete1(WHAT), msgIncomplete2(WHAT);
CHK(msg1.AddString(attrInfoField_Name, "Color") == B_OK);
CHK(msg1.AddString(attrInfoField_PublicName, "The Color") == B_OK);
CHK(msg1.AddInt32(attrInfoField_Type, B_STRING_TYPE) == B_OK);
CHK(msg1.AddBool(attrInfoField_Viewable, true) == B_OK);
CHK(msg1.AddBool(attrInfoField_Editable, true) == B_OK);
CHK(msg1.AddString(attrInfoField_Name, "High Score") == B_OK);
CHK(msg1.AddString(attrInfoField_PublicName, "The Highest Score Ever") == B_OK);
CHK(msg1.AddInt32(attrInfoField_Type, B_INT32_TYPE) == B_OK);
CHK(msg1.AddBool(attrInfoField_Viewable, false) == B_OK);
CHK(msg1.AddBool(attrInfoField_Editable, false) == B_OK);
CHK(msg2.AddString(attrInfoField_Name, "Volume") == B_OK);
CHK(msg2.AddString(attrInfoField_PublicName, "Loudness") == B_OK);
CHK(msg2.AddInt32(attrInfoField_Type, B_DOUBLE_TYPE) == B_OK);
CHK(msg2.AddBool(attrInfoField_Viewable, true) == B_OK);
CHK(msg2.AddBool(attrInfoField_Editable, true) == B_OK);
CHK(msg3.AddString(attrInfoField_Name, "Volume") == B_OK);
CHK(msg3.AddString(attrInfoField_PublicName, "Loudness") == B_OK);
CHK(msg3.AddInt32(attrInfoField_Type, B_DOUBLE_TYPE) == B_OK);
CHK(msg3.AddBool(attrInfoField_Viewable, true) == B_OK);
CHK(msg3.AddBool(attrInfoField_Editable, true) == B_OK);
CHK(msgIncomplete1.AddString(attrInfoField_Name, "Color") == B_OK);
CHK(msgIncomplete1.AddString(attrInfoField_PublicName, "The Color") == B_OK);
CHK(msgIncomplete1.AddInt32(attrInfoField_Type, B_STRING_TYPE) == B_OK);
CHK(msgIncomplete1.AddBool(attrInfoField_Viewable, true) == B_OK);
CHK(msgIncomplete1.AddBool(attrInfoField_Editable, true) == B_OK);
CHK(msgIncomplete1.AddString(attrInfoField_Name, "High Score") == B_OK);
CHK(msgIncomplete1.AddInt32(attrInfoField_Type, B_INT32_TYPE) == B_OK);
CHK(msgIncomplete1.AddBool(attrInfoField_Editable, false) == B_OK);
CHK(msgIncomplete2.AddString(attrInfoField_Name, "Color") == B_OK);
CHK(msgIncomplete2.AddBool(attrInfoField_Editable, true) == B_OK);
CHK(msg1 == msg1);
CHK(msg2 == msg2);
CHK(msg3 == msg3);
CHK(msg1 != msg2);
CHK(msg1 != msg3);
CHK(msg2 == msg3);
NextSubTest();
{
BMimeType mime;
BMessage msg;
CHK(mime.InitCheck() == B_NO_INIT);
CHK(mime.GetAttrInfo(&msg) != B_OK);
CHK(mime.SetAttrInfo(&msg) != B_OK);
}
NextSubTest();
{
#if !TEST_R5
BMessage msg;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.DeleteAttrInfo() != B_OK);
CHK(!mime.IsInstalled());
msg1.RemoveName(typeField);
CHK(mime.SetAttrInfo(&msg1) == B_OK);
CHK(mime.IsInstalled());
CHK(msg != msg1);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg == msg1);
CHK(mime.SetAttrInfo(NULL) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAttrInfo(&msg) != B_OK);
#endif
}
NextSubTest();
{
#if !TEST_R5
BMessage msg;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.DeleteAttrInfo() != B_OK);
CHK(!mime.IsInstalled());
msg1.RemoveName(typeField);
CHK(mime.SetAttrInfo(&msg1) == B_OK);
CHK(mime.IsInstalled());
CHK(msg != msg1);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg == msg1);
CHK(mime.DeleteAttrInfo() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAttrInfo(&msg) != B_OK);
#endif
}
NextSubTest();
{
BMessage msg(WHAT);
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
msgIncomplete1.RemoveName(typeField);
msgIncomplete2.RemoveName(typeField);
CHK(msg != msgIncomplete1);
CHK(msg != msgIncomplete2);
CHK(mime.SetAttrInfo(&msgIncomplete1) == B_OK);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msgIncomplete1.AddString(typeField, testType) == B_OK);
CHK(msgIncomplete2.AddString(typeField, testType) == B_OK);
CHK(msg == msgIncomplete1);
CHK(msg != msgIncomplete2);
}
NextSubTest();
{
BMessage msg(WHAT);
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
msgIncomplete1.RemoveName(typeField);
msgIncomplete2.RemoveName(typeField);
CHK(msg != msgIncomplete1);
CHK(msg != msgIncomplete2);
CHK(mime.SetAttrInfo(&msgIncomplete1) == B_OK);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msgIncomplete1.AddString(typeField, testType) == B_OK);
CHK(msgIncomplete2.AddString(typeField, testType) == B_OK);
CHK(msg == msgIncomplete1);
CHK(msg != msgIncomplete2);
}
NextSubTest();
{
BMimeType mime(testType);
BMessage msgEmpty(WHAT);
BMessage msg(WHAT);
CHK(msg.AddInt32("stuff", 1234) == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(msg != msgEmpty);
CHK(mime.SetAttrInfo(&msgEmpty) == B_OK);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msgEmpty.AddString(typeField, testType) == B_OK);
CHK(msg == msgEmpty);
}
NextSubTest();
{
BMimeType mime(testType);
BMessage msg(WHAT);
BMessage msgExtraSet(msg1);
CHK(msgExtraSet.AddString("extra", ".extra") == B_OK);
CHK(msgExtraSet.AddInt32("more_extras", 123) == B_OK);
CHK(msgExtraSet.AddInt32("more_extras", 456) == B_OK);
CHK(msgExtraSet.AddInt32("more_extras", 789) == B_OK);
BMessage msgExtraGet(msgExtraSet);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msgExtraSet);
CHK(mime.SetAttrInfo(&msgExtraSet) == B_OK);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msgExtraSet.AddString(typeField, testType) == B_OK);
CHK(msg == msgExtraSet);
CHK(msg != msg1);
NextSubTest();
CHK(mime.GetAttrInfo(&msgExtraGet) == B_OK);
CHK(msgExtraGet == msgExtraSet);
CHK(msgExtraGet != msg1);
NextSubTest();
CHK(msgExtraGet.AddInt32("more_extras", 101112) == B_OK);
msgExtraGet.RemoveName(typeField);
CHK(mime.GetAttrInfo(&msgExtraGet) == B_OK);
CHK(msgExtraGet == msgExtraSet);
CHK(msgExtraGet != msg1);
}
NextSubTest();
{
BMimeType mime(testType);
BMessage msg(WHAT);
BMessage msg2(WHAT);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.GetAttrInfo(&msg) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetAttrInfo(&msg) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetAttrInfo(&msg2) == B_OK);
CHK(msg.AddString(typeField, testType) == B_OK);
CHK(msg == msg2);
}
NextSubTest();
{
BMessage msg(WHAT);
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msg2);
CHK(mime.SetAttrInfo(&msg1) == B_OK);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg2.AddString(typeField, testType) == B_OK);
CHK(msg == msg1);
CHK(msg != msg2);
NextSubTest();
CHK(msg.MakeEmpty() == B_OK);
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msg2);
CHK(mime.SetAttrInfo(&msg2) == B_OK);
CHK(mime.GetAttrInfo(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg2.AddString(typeField, testType) == B_OK);
CHK(msg != msg1);
CHK(msg == msg2);
NextSubTest();
CHK(msg.MakeEmpty() == B_OK);
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msg2);
#if !TEST_R5
CHK(mime.SetAttrInfo(NULL) == B_OK);
CHK(mime.GetAttrInfo(&msg) != B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg2.AddString(typeField, testType) == B_OK);
CHK(msg != msg1);
CHK(msg != msg2);
#endif
}
}
void
MimeTypeTest::FileExtensionsTest() {
const int32 WHAT = 234;
BMessage msg1(WHAT), msg2(WHAT), msg3(WHAT);
CHK(msg1.AddString(fileExtField, ".data") == B_OK);
CHK(msg1.AddString(fileExtField, ".txt") == B_OK);
CHK(msg1.AddString(fileExtField, ".png") == B_OK);
CHK(msg1.AddString(fileExtField, ".html") == B_OK);
CHK(msg2.AddString(fileExtField, ".data") == B_OK);
CHK(msg2.AddString(fileExtField, ".txt") == B_OK);
CHK(msg3.AddString(fileExtField, ".data") == B_OK);
CHK(msg3.AddString(fileExtField, ".txt") == B_OK);
CHK(msg1 == msg1);
CHK(msg2 == msg2);
CHK(msg3 == msg3);
CHK(msg1 != msg2);
CHK(msg1 != msg3);
CHK(msg2 == msg3);
NextSubTest();
{
BMessage msg(WHAT);
BMimeType mime;
CHK(mime.InitCheck() == B_NO_INIT);
CHK(mime.GetFileExtensions(&msg) != B_OK);
CHK(mime.SetFileExtensions(&msg) != B_OK);
}
NextSubTest();
{
#if !TEST_R5
BMessage msg;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.DeleteFileExtensions() != B_OK);
CHK(!mime.IsInstalled());
msg1.RemoveName(typeField);
CHK(mime.SetFileExtensions(&msg1) == B_OK);
CHK(mime.IsInstalled());
CHK(msg != msg1);
CHK(mime.GetFileExtensions(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg == msg1);
CHK(mime.SetFileExtensions(NULL) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetFileExtensions(&msg) != B_OK);
#endif
}
NextSubTest();
{
#if !TEST_R5
BMessage msg;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.DeleteFileExtensions() != B_OK);
CHK(!mime.IsInstalled());
msg1.RemoveName(typeField);
CHK(mime.SetFileExtensions(&msg1) == B_OK);
CHK(mime.IsInstalled());
CHK(msg != msg1);
CHK(mime.GetFileExtensions(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg == msg1);
CHK(mime.DeleteFileExtensions() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetFileExtensions(&msg) != B_OK);
#endif
}
NextSubTest();
{
BMimeType mime(testType);
BMessage msgEmpty(WHAT);
BMessage msg(WHAT);
CHK(msg.AddInt32("stuff", 1234) == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(msg != msgEmpty);
CHK(mime.SetFileExtensions(&msgEmpty) == B_OK);
CHK(mime.GetFileExtensions(&msg) == B_OK);
CHK(msgEmpty.AddString(typeField, testType) == B_OK);
CHK(msg == msgEmpty);
}
NextSubTest();
{
BMimeType mime(testType);
BMessage msg(WHAT);
BMessage msgExtraSet(msg1);
CHK(msgExtraSet.AddString("extra", ".extra") == B_OK);
CHK(msgExtraSet.AddInt32("more_extras", 123) == B_OK);
CHK(msgExtraSet.AddInt32("more_extras", 456) == B_OK);
CHK(msgExtraSet.AddInt32("more_extras", 789) == B_OK);
BMessage msgExtraGet(msgExtraSet);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msgExtraSet);
CHK(mime.SetFileExtensions(&msgExtraSet) == B_OK);
CHK(mime.GetFileExtensions(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msgExtraSet.AddString(typeField, testType) == B_OK);
CHK(msg == msgExtraSet);
CHK(msg != msg1);
NextSubTest();
CHK(mime.GetFileExtensions(&msgExtraGet) == B_OK);
CHK(msgExtraGet == msgExtraSet);
CHK(msgExtraGet != msg1);
NextSubTest();
CHK(msgExtraGet.AddInt32("more_extras", 101112) == B_OK);
msgExtraGet.RemoveName(typeField);
CHK(mime.GetFileExtensions(&msgExtraGet) == B_OK);
CHK(msgExtraGet == msgExtraSet);
CHK(msgExtraGet != msg1);
}
NextSubTest();
{
BMessage msg(WHAT);
BMimeType mime(testType);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msg2);
CHK(mime.SetFileExtensions(&msg1) == B_OK);
CHK(mime.GetFileExtensions(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg2.AddString(typeField, testType) == B_OK);
CHK(msg == msg1);
CHK(msg != msg2);
NextSubTest();
CHK(msg.MakeEmpty() == B_OK);
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msg2);
CHK(mime.SetFileExtensions(&msg2) == B_OK);
CHK(mime.GetFileExtensions(&msg) == B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg2.AddString(typeField, testType) == B_OK);
CHK(msg != msg1);
CHK(msg == msg2);
NextSubTest();
CHK(msg.MakeEmpty() == B_OK);
msg1.RemoveName(typeField);
msg2.RemoveName(typeField);
CHK(msg != msg1);
CHK(msg != msg2);
#if !TEST_R5
CHK(mime.SetFileExtensions(NULL) == B_OK);
CHK(mime.GetFileExtensions(&msg) != B_OK);
CHK(msg1.AddString(typeField, testType) == B_OK);
CHK(msg2.AddString(typeField, testType) == B_OK);
CHK(msg != msg1);
CHK(msg != msg2);
#endif
}
}
void
MimeTypeTest::IconTest(IconHelper &helper) {
BBitmap *bmp = helper.TempBitmap();
NextSubTest();
{
BMimeType mime;
CHK(mime.InitCheck() == B_NO_INIT);
CHK(helper.GetIcon(mime, bmp) != B_OK);
CHK(helper.SetIcon(mime, bmp) != B_OK);
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(helper.GetIcon(mime, bmp) != B_OK);
CHK(!mime.IsInstalled());
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(mime.IsInstalled());
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(helper.GetIcon(mime, NULL) != B_OK);
CHK(!mime.IsInstalled());
CHK(helper.SetIcon(mime, NULL) != B_OK);
#if TEST_R5
CHK(mime.IsInstalled());
#else
CHK(!mime.IsInstalled());
CHK(mime.Install() == B_OK);
#endif
CHK(helper.GetIcon(mime, bmp) != B_OK);
CHK(helper.GetIcon(mime, NULL) != B_OK);
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
CHK(helper.SetIcon(mime, NULL) == B_OK);
CHK(helper.GetIcon(mime, bmp) != B_OK);
}
NextSubTest();
{
#if !TEST_R5
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(helper.DeleteIcon(mime) != B_OK);
CHK(!mime.IsInstalled());
CHK(helper.SetIcon(mime, helper.Bitmap2()) == B_OK);
CHK(mime.IsInstalled());
fill_bitmap(*bmp, 100);
CHK(*bmp != *helper.Bitmap2());
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap2());
CHK(helper.DeleteIcon(mime) == B_OK);
CHK(mime.IsInstalled());
CHK(helper.GetIcon(mime, bmp) != B_OK);
#endif
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
BBitmap testBmp(BRect(0,0,9,9), B_CMAP8);
fill_bitmap(testBmp, 3);
CHK(testBmp != *helper.Bitmap1());
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
CHK(helper.SetIcon(mime, &testBmp) != B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
CHK(*bmp != testBmp);
fill_bitmap(testBmp, 3);
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(helper.GetIcon(mime, &testBmp) != B_OK);
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
BBitmap testBmp(BRect(0,0,99,99), B_CMAP8);
fill_bitmap(testBmp, 3);
CHK(testBmp != *helper.Bitmap1());
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
CHK(helper.SetIcon(mime, &testBmp) != B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
CHK(*bmp != testBmp);
fill_bitmap(testBmp, 3);
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(helper.GetIcon(mime, &testBmp) != B_OK);
}
NextSubTest();
{
#if !TEST_R5
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
BBitmap testBmp(helper.BitmapBounds(), B_RGB32);
fill_bitmap32(testBmp, 10, 20, 30, 40);
BBitmap testBmp8(helper.BitmapBounds(), B_CMAP8);
reduce_color_depth(testBmp, testBmp8);
CHK(testBmp != *helper.Bitmap1());
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
CHK(helper.SetIcon(mime, &testBmp) == B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp != *helper.Bitmap1());
CHK(*bmp != testBmp);
CHK(*bmp == testBmp8);
#endif
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
fill_bitmap(*bmp, 3);
CHK(*bmp != *helper.Bitmap1());
CHK(helper.SetIcon(mime, helper.Bitmap1()) == B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap1());
fill_bitmap(*bmp, 3);
CHK(helper.SetIcon(mime, helper.Bitmap2()) == B_OK);
CHK(helper.GetIcon(mime, bmp) == B_OK);
CHK(*bmp == *helper.Bitmap2());
CHK(*bmp != *helper.Bitmap1());
}
}
void
MimeTypeTest::IconForTypeTest(IconForTypeHelper &helper) {
IconTest(helper);
BBitmap *bmp = helper.TempBitmap();
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
fill_bitmap(*bmp, 3);
CHK(*bmp != *helper.Bitmap1());
CHK(mime.SetIconForType(testTypeInvalid, helper.Bitmap1(), helper.Size()) != B_OK);
CHK(mime.GetIconForType(testTypeInvalid, bmp, helper.Size()) != B_OK);
CHK(*bmp != *helper.Bitmap1());
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
fill_bitmap(*bmp, 3);
CHK(*bmp != *helper.Bitmap1());
CHK(mime.SetIconForType(NULL, helper.Bitmap1(), helper.Size()) == B_OK);
CHK(mime.GetIconForType(NULL, bmp, helper.Size()) == B_OK);
CHK(*bmp == *helper.Bitmap1());
fill_bitmap(*bmp, 3);
CHK(*bmp != *helper.Bitmap1());
CHK(mime.GetIcon(bmp, helper.Size()) == B_OK);
CHK(*bmp == *helper.Bitmap1());
CHK(mime.SetIconForType(NULL, NULL, helper.Size()) == B_OK);
CHK(mime.GetIconForType(NULL, bmp, helper.Size()) != B_OK);
CHK(mime.GetIcon(bmp, helper.Size()) != B_OK);
}
}
void
MimeTypeTest::LargeIconTest() {
IconHelper helper(B_LARGE_ICON);
IconTest(helper);
}
void
MimeTypeTest::MiniIconTest() {
IconHelper helper(B_MINI_ICON);
IconTest(helper);
}
void
MimeTypeTest::LargeIconForTypeTest() {
IconForTypeHelper helper(testType, B_LARGE_ICON);
IconForTypeTest(helper);
}
void
MimeTypeTest::MiniIconForTypeTest() {
IconForTypeHelper helper(testType, B_MINI_ICON);
IconForTypeTest(helper);
}
bool isMIMESupertype(const char *type) {
BMimeType sub, super;
status_t err;
err = !type || !BMimeType::IsValid(type);
if (!err)
err = sub.SetTo(type);
if (!err)
return sub.GetSupertype(&super) == B_BAD_VALUE;
return false;
}
void
MimeTypeTest::VerifyInstalledTypes() {
NextSubTest();
{
BMessage msg;
CHK(BMimeType::GetInstalledTypes(&msg) == B_OK);
std::set<std::string> typeSet;
SetAdapter typeAdapter(typeSet);
FillWithMimeTypes(typeAdapter, msg, "types");
BDirectory rootDir(mimeDatabaseDir.c_str());
BEntry superEntry;
CHK(rootDir.InitCheck() == B_OK);
rootDir.Rewind();
while (true) {
status_t err = rootDir.GetNextEntry(&superEntry);
if (err == B_ENTRY_NOT_FOUND)
break;
CHK(!err);
char superLeafMixed[B_PATH_NAME_LENGTH+1];
CHK(superEntry.GetName(superLeafMixed) == B_OK);
std::string superLeaf;
to_lower(superLeafMixed, superLeaf);
if (superEntry.IsDirectory() && BMimeType::IsValid(superLeaf.c_str())) {
CHK(typeSet.find(superLeaf.c_str()) != typeSet.end());
typeSet.erase(superLeaf.c_str());
BDirectory superDir(&superEntry);
BEntry subEntry;
CHK(superDir.InitCheck() == B_OK);
superDir.Rewind();
while (true) {
status_t err = superDir.GetNextEntry(&subEntry);
if (err == B_ENTRY_NOT_FOUND)
break;
CHK(!err);
char subLeafMixed[B_PATH_NAME_LENGTH+1];
CHK(subEntry.GetName(subLeafMixed) == B_OK);
std::string subLeaf;
to_lower(subLeafMixed, subLeaf);
std::string subType = superLeaf + "/" + subLeaf;
if (BMimeType::IsValid(subType.c_str())) {
if (typeSet.find(subType.c_str()) == typeSet.end())
cout << "Fuckup == '" << subType << "'" << endl;
CHK(typeSet.find(subType.c_str()) != typeSet.end());
typeSet.erase(subType.c_str());
}
}
}
}
CHK(typeSet.size() == 0);
}
NextSubTest();
{
BMessage msg;
CHK(BMimeType::GetInstalledSupertypes(&msg) == B_OK);
std::set<std::string> typeSet;
SetAdapter typeAdapter(typeSet);
FillWithMimeTypes(typeAdapter, msg, "super_types");
BDirectory rootDir(mimeDatabaseDir.c_str());
BEntry superEntry;
CHK(rootDir.InitCheck() == B_OK);
rootDir.Rewind();
while (true) {
status_t err = rootDir.GetNextEntry(&superEntry);
if (err == B_ENTRY_NOT_FOUND)
break;
CHK(!err);
char superLeafMixed[B_PATH_NAME_LENGTH+1];
CHK(superEntry.GetName(superLeafMixed) == B_OK);
std::string superLeaf;
to_lower(superLeafMixed, superLeaf);
if (superEntry.IsDirectory() && BMimeType::IsValid(superLeaf.c_str())) {
CHK(typeSet.find(superLeaf.c_str()) != typeSet.end());
typeSet.erase(superLeaf.c_str());
BMessage msg;
CHK(BMimeType::GetInstalledTypes(superLeaf.c_str(), &msg) == B_OK);
std::set<std::string> subtypeSet;
SetAdapter subtypeAdapter(subtypeSet);
FillWithMimeTypes(subtypeAdapter, msg, "types");
BDirectory superDir(&superEntry);
BEntry subEntry;
CHK(superDir.InitCheck() == B_OK);
superDir.Rewind();
while (true) {
status_t err = superDir.GetNextEntry(&subEntry);
if (err == B_ENTRY_NOT_FOUND)
break;
CHK(!err);
char subLeafMixed[B_PATH_NAME_LENGTH+1];
CHK(subEntry.GetName(subLeafMixed) == B_OK);
std::string subLeaf;
to_lower(subLeafMixed, subLeaf);
std::string subType = superLeaf + "/" + subLeaf;
if (BMimeType::IsValid(subType.c_str())) {
CHK(subtypeSet.find(subType.c_str()) != subtypeSet.end());
subtypeSet.erase(subType.c_str());
}
}
CHK(subtypeSet.size() == 0);
}
}
CHK(typeSet.size() == 0);
}
}
void
MimeTypeTest::InstalledTypesTest() {
{
BMessage msg;
NextSubTest();
#if !TEST_R5
CHK(BMimeType::GetInstalledTypes(NULL) != B_OK);
#endif
NextSubTest();
#if !TEST_R5
CHK(BMimeType::GetInstalledTypes("text", NULL) != B_OK);
#endif
NextSubTest();
CHK(BMimeType::GetInstalledTypes(NULL, &msg) == B_OK);
NextSubTest();
#if !TEST_R5
CHK(BMimeType::GetInstalledTypes(NULL, NULL) != B_OK);
#endif
NextSubTest();
#if !TEST_R5
CHK(BMimeType::GetInstalledSupertypes(NULL) != B_OK);
#endif
}
{
BMessage msg;
NextSubTest();
CHK(!BMimeType::IsValid(testTypeSuperInvalid));
CHK(BMimeType::GetInstalledTypes(testTypeSuperInvalid, &msg) != B_OK);
NextSubTest();
CHK(BMimeType::IsValid(testTypeSuperValid));
CHK(BMimeType::GetInstalledTypes(testTypeSuperValid, &msg) != B_OK);
}
{
VerifyInstalledTypes();
BMimeType mime(testTypeApp1);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled()) {
CHK(mime.Delete() == B_OK);
VerifyInstalledTypes();
CHK(mime.Install() == B_OK);
VerifyInstalledTypes();
} else {
CHK(mime.Install() == B_OK);
VerifyInstalledTypes();
CHK(mime.Delete() == B_OK);
VerifyInstalledTypes();
}
}
}
void
MimeTypeTest::ShortDescriptionTest() {
DescriptionTest(&BMimeType::GetShortDescription, &BMimeType::SetShortDescription,
#if TEST_R5
NULL
#else
&BMimeType::DeleteShortDescription
#endif
);
}
void
MimeTypeTest::LongDescriptionTest() {
DescriptionTest(&BMimeType::GetLongDescription, &BMimeType::SetLongDescription,
#if TEST_R5
NULL
#else
&BMimeType::DeleteLongDescription
#endif
);
}
void
MimeTypeTest::DescriptionTest(GetDescriptionFunc getDescr, SetDescriptionFunc setDescr,
DeleteDescriptionFunc deleteDescr)
{
char str[B_MIME_TYPE_LENGTH+1];
NextSubTest();
{
str[0] = 0;
BMimeType mime;
CPPUNIT_ASSERT(mime.InitCheck() == B_NO_INIT);
CPPUNIT_ASSERT((mime.*getDescr)(str) != B_OK);
CPPUNIT_ASSERT((mime.*setDescr)(str) != B_OK);
}
NextSubTest();
{
str[0] = 0;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK((mime.*getDescr)(str) != B_OK);
CHK(!mime.IsInstalled());
CHK((mime.*setDescr)(testDescr) == B_OK);
CHK(mime.IsInstalled());
CHK((mime.*getDescr)(str) == B_OK);
CHK(strcmp(str, testDescr) == 0);
}
NextSubTest();
{
#if !TEST_R5
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK((mime.*getDescr)(NULL) == B_BAD_VALUE);
CHK(!mime.IsInstalled());
CHK((mime.*setDescr)(NULL) == B_ENTRY_NOT_FOUND);
CHK(!mime.IsInstalled());
CHK((mime.*setDescr)(testDescr) == B_OK);
CHK(mime.IsInstalled());
str[0] = 0;
CHK((mime.*getDescr)(str) == B_OK);
CHK(strcmp(str, testDescr) == 0);
CHK((mime.*setDescr)(NULL) == B_OK);
CHK(mime.IsInstalled());
CHK((mime.*getDescr)(str) == B_ENTRY_NOT_FOUND);
#endif
}
NextSubTest();
{
#if !TEST_R5
entry_ref ref;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK((mime.*deleteDescr)() != B_OK);
CHK(!mime.IsInstalled());
CHK((mime.*setDescr)(testDescr) == B_OK);
CHK(mime.IsInstalled());
str[0] = 0;
CHK((mime.*getDescr)(str) == B_OK);
CHK(strcmp(str, testDescr) == 0);
CHK((mime.*deleteDescr)() == B_OK);
CHK(mime.IsInstalled());
CHK((mime.*getDescr)(str) != B_OK);
#endif
}
NextSubTest();
{
str[0] = 0;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK((mime.*getDescr)(str) == B_ENTRY_NOT_FOUND);
CHK((mime.*setDescr)(testDescr) == B_OK);
CHK((mime.*getDescr)(str) == B_OK);
CHK(strcmp(str, testDescr) == 0);
CHK((mime.*setDescr)(testDescr2) == B_OK);
CHK((mime.*getDescr)(str) == B_OK);
CHK(strcmp(str, testDescr2) == 0);
}
NextSubTest();
{
str[0] = 0;
CHK(strlen(longDescr) > (B_MIME_TYPE_LENGTH+1));
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK((mime.*setDescr)(longDescr) != B_OK);
CHK((mime.*getDescr)(str) == B_ENTRY_NOT_FOUND);
CHK((mime.*setDescr)(testDescr) == B_OK);
CHK((mime.*setDescr)(longDescr) != B_OK);
CHK((mime.*getDescr)(str) == B_OK);
CHK(strcmp(str, testDescr) == 0);
}
}
void
MimeTypeTest::PreferredAppTest() {
char str[B_MIME_TYPE_LENGTH+1];
sprintf(str, "%s", testSig);
NextSubTest();
{
BMimeType mime;
CPPUNIT_ASSERT(mime.InitCheck() == B_NO_INIT);
CPPUNIT_ASSERT(mime.GetPreferredApp(str) != B_OK);
CPPUNIT_ASSERT(mime.SetPreferredApp(str) != B_OK);
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.GetPreferredApp(str) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetPreferredApp(testSig) == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetPreferredApp(str) == B_OK);
CHK(strcmp(str, testSig) == 0);
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
#if TEST_R5
CHK(!mime.IsInstalled());
CHK(mime.GetPreferredApp(NULL) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetPreferredApp(NULL) != B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetPreferredApp(str) == B_ENTRY_NOT_FOUND);
#else
CHK(!mime.IsInstalled());
CHK(mime.GetPreferredApp(NULL) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetPreferredApp(NULL) != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetPreferredApp(testSig) == B_OK);
CHK(mime.IsInstalled());
str[0] = 0;
CHK(mime.GetPreferredApp(str) == B_OK);
CHK(strcmp(str, testSig) == 0);
CHK(mime.SetPreferredApp(NULL) == B_OK);
CHK(mime.IsInstalled());
str[0] = 0;
CHK(mime.GetPreferredApp(str) != B_OK);
#endif
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetPreferredApp(NULL) != B_OK);
CHK(mime.SetPreferredApp(NULL) != B_OK);
CHK(mime.GetPreferredApp(NULL) != B_OK);
}
NextSubTest();
{
#if !TEST_R5
entry_ref ref;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.DeletePreferredApp() != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.SetPreferredApp(testSig) == B_OK);
CHK(mime.IsInstalled());
str[0] = 0;
CHK(mime.GetPreferredApp(str) == B_OK);
CHK(strcmp(str, testSig) == 0);
CHK(mime.DeletePreferredApp() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetPreferredApp(str) != B_OK);
#endif
}
NextSubTest();
{
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.GetPreferredApp(str) == B_ENTRY_NOT_FOUND);
CHK(mime.SetPreferredApp(testSig) == B_OK);
CHK(mime.GetPreferredApp(str) == B_OK);
CHK(strcmp(str, testSig) == 0);
CHK(mime.SetPreferredApp(testSig2) == B_OK);
CHK(mime.GetPreferredApp(str) == B_OK);
CHK(strcmp(str, testSig2) == 0);
}
NextSubTest();
{
CHK(strlen(longDescr) > (B_MIME_TYPE_LENGTH+1));
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.SetPreferredApp(longSig) != B_OK);
CHK(mime.GetPreferredApp(str) == B_ENTRY_NOT_FOUND);
CHK(mime.SetPreferredApp(testSig) == B_OK);
CHK(mime.SetPreferredApp(longSig) != B_OK);
CHK(mime.GetPreferredApp(str) == B_OK);
CHK(strcmp(str, testSig) == 0);
}
}
void
to_lower(const char *str, std::string &result) {
CHK(str != NULL);
result = "";
for (uint i = 0; i < strlen(str); i++)
result += tolower(str[i]);
}
std::string
to_lower(const char *str) {
std::string result;
to_lower(str, result);
return result;
}
void
remove_type(const char *type, const char *databaseDir) {
CHK(type != NULL);
std::string typeLower;
to_lower(type, typeLower);
BEntry entry((std::string(mimeDatabaseDir) + "/" + typeLower).c_str());
CHK(entry.InitCheck() == B_OK);
if (entry.Exists())
CHK(entry.Remove() == B_OK);
CHK(!entry.Exists());
}
bool
type_exists(const char *type, const char *databaseDir) {
CHK(type != NULL);
std::string typeLower;
to_lower(type, typeLower);
BEntry entry((std::string(databaseDir) + "/" + typeLower).c_str());
CHK(entry.InitCheck() == B_OK);
return entry.Exists();
}
void
MimeTypeTest::InstallDeleteTest() {
NextSubTest();
{
BMimeType mime;
CHK(mime.InitCheck() == B_NO_INIT);
CHK(!mime.IsInstalled());
CHK(mime.Install() != B_OK);
CHK(mime.Delete() != B_OK);
}
NextSubTest();
{
BMimeType mime(testTypeInvalid);
CHK(mime.InitCheck() != B_OK);
CHK(!mime.IsInstalled());
CHK(mime.Install() != B_OK);
CHK(mime.Delete() != B_OK);
}
NextSubTest();
{
remove_type(testType);
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
CHK(!mime.IsInstalled());
CHK(mime.Delete() != B_OK);
CHK(!type_exists(testType));
CHK(mime.Install() == B_OK);
CHK(type_exists(testType));
CHK(mime.IsInstalled());
#if !TEST_R5
CHK(mime.Install() != B_OK);
#endif
CHK(mime.Delete() == B_OK);
CHK(!type_exists(testType));
CHK(!mime.IsInstalled());
}
}
void FillWithMimeTypes(ContainerAdapter &container, BMessage &typeMessage, const char* fieldName) {
type_code type;
int32 count;
status_t err;
err = typeMessage.GetInfo(fieldName, &type, &count);
if (err == B_NAME_NOT_FOUND)
count = 0;
else
CHK(err == B_OK);
for (int i = 0; i < count; i++) {
char *str;
CHK(typeMessage.FindString(fieldName, i, (const char**)&str) == B_OK);
std::string strLower;
to_lower(str, strLower);
if (BMimeType::IsValid(strLower.c_str()))
container.Add(strLower);
}
}
bool
types_fields_are_identical(const BMessage &msg1, const BMessage &msg2)
{
const char *str1;
const char *str2;
int i = 0;
bool result = true;
while (true) {
status_t err1 = msg1.FindString(typesField, i, &str1);
status_t err2 = msg2.FindString(typesField, i, &str2);
if (err1 != err2) {
result = false;
break;
}
if (err1 != B_OK)
break;
result &= to_lower(str1) == to_lower(str2);
i++;
}
return result;
}
bool
is_supporting_app_for_all_types_in_message(const char *app, const BMessage &msg)
{
const char *str;
bool result = true;
for (int i = 0; msg.FindString(typesField, i, &str) == B_OK; i++) {
BMimeType supportedType(str);
BMessage appMsg;
CHK(supportedType.InitCheck() == B_OK);
CHK(supportedType.GetSupportingApps(&appMsg) == B_OK);
int32 directlySupportingAppsCount;
CHK(appMsg.FindInt32("be:sub", &directlySupportingAppsCount) == B_OK);
bool foundType = false;
const char *supportingApp;
for (int j = 0;
j < directlySupportingAppsCount
&& appMsg.FindString(applicationsField, &supportingApp) == B_OK;
j++)
{
foundType |= to_lower(app) == to_lower(supportingApp);
}
result &= foundType;
}
return result;
}
void
MimeTypeTest::SupportedTypesTest() {
#if TEST_R5
Outputf("(no tests actually performed for R5 version)\n");
#else
const int32 WHAT = 0;
BMessage msg1a(WHAT), msg1b(WHAT), msg2(WHAT), msg3(WHAT), msgEmpty(WHAT);
CHK(msg3.AddString(typesField, testType1) == B_OK);
CHK(msg3.AddString(typesField, testType2) == B_OK);
CHK(msg3.AddString(typesField, testType3) == B_OK);
CHK(msg2.AddString(typesField, testType2) == B_OK);
CHK(msg2.AddString(typesField, testType3) == B_OK);
CHK(msg1a.AddString(typesField, testType5) == B_OK);
CHK(msg1b.AddString(typesField, testType2) == B_OK);
CHK(msg1a == msg1a);
CHK(msg1b == msg1b);
CHK(msg2 == msg2);
CHK(msg3 == msg3);
CHK(msg1a != msg2);
CHK(msg1a != msg3);
CHK(msg1a != msgEmpty);
NextSubTest();
{
BMimeType mime;
BMessage msg;
CHK(mime.InitCheck() == B_NO_INIT);
CHK(mime.SetSupportedTypes(&msg, true) != B_OK);
CHK(mime.SetSupportedTypes(&msg, false) != B_OK);
CHK(mime.GetSupportedTypes(&msg) != B_OK);
CHK(mime.DeleteSupportedTypes() != B_OK);
}
NextSubTest();
{
BMessage msg;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.SetSupportedTypes(&msg3, true) == B_OK);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == true);
CHK(mime.Delete() == B_OK);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == false);
}
NextSubTest();
{
BMessage msg;
BMimeType mime(testType);
CHK(mime.InitCheck() == B_OK);
if (mime.IsInstalled())
CHK(mime.Delete() == B_OK);
if (!mime.IsInstalled())
CHK(mime.Install() == B_OK);
CHK(mime.IsInstalled());
CHK(mime.SetSupportedTypes(&msg3, true) == B_OK);
CHK(mime.GetSupportedTypes(&msg) == B_OK);
CHK(types_fields_are_identical(msg3, msg) == true);
CHK(types_fields_are_identical(msg2, msg) == false);
CHK(types_fields_are_identical(msg1a, msg) == false);
CHK(types_fields_are_identical(msg1b, msg) == false);
CHK(types_fields_are_identical(msgEmpty, msg) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg2) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1a) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1b) == true);
CHK(mime.SetSupportedTypes(&msg2, false) == B_OK);
CHK(mime.GetSupportedTypes(&msg) == B_OK);
CHK(types_fields_are_identical(msg3, msg) == false);
CHK(types_fields_are_identical(msg2, msg) == true);
CHK(types_fields_are_identical(msg1a, msg) == false);
CHK(types_fields_are_identical(msg1b, msg) == false);
CHK(types_fields_are_identical(msgEmpty, msg) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg2) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1a) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1b) == true);
CHK(mime.SetSupportedTypes(&msg1a, false) == B_OK);
CHK(mime.GetSupportedTypes(&msg) == B_OK);
CHK(types_fields_are_identical(msg3, msg) == false);
CHK(types_fields_are_identical(msg2, msg) == false);
CHK(types_fields_are_identical(msg1a, msg) == true);
CHK(types_fields_are_identical(msg1b, msg) == false);
CHK(types_fields_are_identical(msgEmpty, msg) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg2) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1a) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1b) == true);
CHK(mime.SetSupportedTypes(&msg1b, false) == B_OK);
CHK(mime.GetSupportedTypes(&msg) == B_OK);
CHK(types_fields_are_identical(msg3, msg) == false);
CHK(types_fields_are_identical(msg2, msg) == false);
CHK(types_fields_are_identical(msg1a, msg) == false);
CHK(types_fields_are_identical(msg1b, msg) == true);
CHK(types_fields_are_identical(msgEmpty, msg) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg2) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1a) == true);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1b) == true);
CHK(mime.SetSupportedTypes(&msg1b, true) == B_OK);
CHK(mime.GetSupportedTypes(&msg) == B_OK);
CHK(types_fields_are_identical(msg3, msg) == false);
CHK(types_fields_are_identical(msg2, msg) == false);
CHK(types_fields_are_identical(msg1a, msg) == false);
CHK(types_fields_are_identical(msg1b, msg) == true);
CHK(types_fields_are_identical(msgEmpty, msg) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg2) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1a) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1b) == true);
CHK(mime.SetSupportedTypes(NULL, false) == B_OK);
CHK(mime.GetSupportedTypes(&msg) == B_ENTRY_NOT_FOUND);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg2) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1a) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1b) == true);
CHK(mime.SetSupportedTypes(NULL, true) == B_ENTRY_NOT_FOUND);
CHK(mime.GetSupportedTypes(&msg) == B_ENTRY_NOT_FOUND);
CHK(is_supporting_app_for_all_types_in_message(testType, msg3) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg2) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1a) == false);
CHK(is_supporting_app_for_all_types_in_message(testType, msg1b) == false);
}
#endif
}
void
MimeTypeTest::SupportingAppsTest() {
NextSubTest();
if (true)
{
std::set<std::string> typeList;
std::set<std::string> appList;
std::map< std::string, std::set<std::string> > typeAppMap;
std::map< std::string, std::set<std::string> > fakeTypeAppMap;
{
BMessage msg;
CHK(BMimeType::GetInstalledTypes(&msg) == B_OK);
SetAdapter typeAdapter(typeList);
FillWithMimeTypes(typeAdapter, msg, "types");
}
{
BMessage msg;
CHK(BMimeType::GetInstalledTypes(applicationSupertype, &msg) == B_OK);
SetAdapter appAdapter(appList);
FillWithMimeTypes(appAdapter, msg, "types");
}
{
std::set<std::string>::iterator i;
for (i = appList.begin(); i != appList.end(); i++) {
std::string app = *i;
std::string appFile = std::string(mimeDatabaseDir) + "/" + app;
BNode node(appFile.c_str());
CHK(node.InitCheck() == B_OK);
attr_info info;
if (node.GetAttrInfo("META:FILE_TYPES", &info) == B_OK) {
char *buffer = new char[info.size+1];
CHK(node.ReadAttr("META:FILE_TYPES", B_MESSAGE_TYPE, 0, buffer, info.size) == info.size);
BMessage msg;
if (msg.Unflatten(buffer) == B_OK) {
std::set<std::string> supportList;
SetAdapter supportAdapter(supportList);
FillWithMimeTypes(supportAdapter, msg, "types");
for (std::set<std::string>::iterator type = supportList.begin();
type != supportList.end();
type++)
{
NextSubTest();
typeAppMap[*type].insert(app);
fakeTypeAppMap[*type].insert(app);
}
} else {
printf("Warning: Unable to unflatten META:FILE_TYPES attribute for '%s' type.\n",
app.c_str());
}
delete buffer;
}
}
}
{
BEntry entry((std::string(mimeDatabaseDir) + "/__mime_table").c_str());
CHK(entry.InitCheck() == B_OK);
if (entry.Exists()) {
BFile file(&entry, B_READ_ONLY);
CHK(file.InitCheck() == B_OK);
BMessage msg;
CHK(msg.Unflatten(&file) == B_OK);
char *type;
uint32 typeVal;
int32 count;
for (int i = 0; msg.GetInfo(B_STRING_TYPE, i, &type, &typeVal, &count) == B_OK; i++ ) {
const char *app;
for (int j = 0; j < count; j++) {
CHK(msg.FindString(type, j, &app) == B_OK);
#if TEST_R5
typeAppMap[type].insert(to_lower(app));
#else
fakeTypeAppMap[type].insert(to_lower(app));
#endif
}
}
}
}
for (std::set<std::string>::iterator i = typeList.begin(); i != typeList.end(); i++) {
std::string type = *i;
BMimeType mime(type.c_str());
CHK(mime.InitCheck() == B_OK);
std::set<std::string> appSetSuper;
BMimeType superType;
if (mime.GetSupertype(&superType) == B_OK)
appSetSuper = typeAppMap[superType.Type()];
BMessage msg;
CHK(mime.GetSupportingApps(&msg) == B_OK);
std::queue<std::string> appList;
QueueAdapter appAdapter(appList);
FillWithMimeTypes(appAdapter, msg, "applications");
}
}
}
void
MimeTypeTest::WildcardAppsTest() {
NextSubTest();
{
#if TEST_R5
CHK(BMimeType::GetWildcardApps(NULL) == B_OK);
#else
CHK(BMimeType::GetWildcardApps(NULL) == B_BAD_VALUE);
#endif
}
NextSubTest();
{
BMessage msg1, msg2;
CHK(BMimeType::GetWildcardApps(&msg1) == B_OK);
BMimeType mime(wildcardType);
CHK(mime.InitCheck() == B_OK);
CHK(mime.GetSupportingApps(&msg2) == B_OK);
CHK(msg1 == msg2);
}
}
static
void
init_long_types(char *notTooLongType, char *tooLongType)
{
#ifdef TEST_R5
const int notTooLongLength = B_MIME_TYPE_LENGTH;
#else
const int notTooLongLength = B_MIME_TYPE_LENGTH - 1;
#endif
const int tooLongLength = notTooLongLength + 1;
strcpy(notTooLongType, "image/");
memset(notTooLongType + strlen(notTooLongType), 'a',
notTooLongLength - strlen(notTooLongType));
notTooLongType[notTooLongLength] = '\0';
strcpy(tooLongType, "image/");
memset(tooLongType + strlen(tooLongType), 'a',
tooLongLength - strlen(tooLongType));
tooLongType[tooLongLength] = '\0';
}
void
MimeTypeTest::InitTest()
{
const char *validType = "image/gif";
const char *validType2 = "application/octet-stream";
const char *invalidType = "invalid type";
char notTooLongType[B_MIME_TYPE_LENGTH + 3];
char tooLongType[B_MIME_TYPE_LENGTH + 3];
init_long_types(notTooLongType, tooLongType);
NextSubTest();
{
BMimeType type;
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type(validType);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == validType);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type(invalidType);
CHK(type.InitCheck() == B_BAD_VALUE);
CHK(type.Type() == NULL);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type(notTooLongType);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == notTooLongType);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type(tooLongType);
CHK(type.InitCheck() == B_BAD_VALUE);
CHK(type.Type() == NULL);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetTo(validType) == B_OK);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == validType);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetTo(invalidType) == B_BAD_VALUE);
CHK(type.InitCheck() == B_BAD_VALUE);
CHK(type.Type() == NULL);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetTo(notTooLongType) == B_OK);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == notTooLongType);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetTo(tooLongType) == B_BAD_VALUE);
CHK(type.InitCheck() == B_BAD_VALUE);
CHK(type.Type() == NULL);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetType(validType) == B_OK);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == validType);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetType(invalidType) == B_BAD_VALUE);
CHK(type.InitCheck() == B_BAD_VALUE);
CHK(type.Type() == NULL);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetType(notTooLongType) == B_OK);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == notTooLongType);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type;
CHK(type.SetType(tooLongType) == B_BAD_VALUE);
CHK(type.InitCheck() == B_BAD_VALUE);
CHK(type.Type() == NULL);
type.Unset();
CHK(type.InitCheck() == B_NO_INIT);
CHK(type.Type() == NULL);
}
NextSubTest();
{
BMimeType type(validType);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == validType);
CHK(type.SetTo(validType2) == B_OK);
CHK(type.InitCheck() == B_OK);
CHK(string(type.Type()) == validType2);
}
NextSubTest();
{
BMimeType type(NULL);
CHK(type.Type() == NULL);
CHK(type.InitCheck() != B_OK);
CHK(type.Type() == NULL);
CHK(type.SetTo(NULL) != B_OK);
CHK(type.Type() == NULL);
CHK(type.SetType(NULL) != B_OK);
CHK(type.Type() == NULL);
}
}
void
MimeTypeTest::StringTest()
{
char notTooLongType[B_MIME_TYPE_LENGTH + 3];
char tooLongType[B_MIME_TYPE_LENGTH + 3];
init_long_types(notTooLongType, tooLongType);
struct mime_type_test {
const char *type;
bool super_type;
status_t error;
};
mime_type_test tests[] = {
{ "application", true, B_OK, },
{ "application/octet-stream", false, B_OK, },
{ "audio", true, B_OK, },
{ "audio/x-aiff", false, B_OK, },
{ "image", true, B_OK, },
{ "image/gif", false, B_OK, },
{ "message", true, B_OK, },
{ "message/rfc822", false, B_OK, },
{ "multipart", true, B_OK, },
{ "multipart/mixed", false, B_OK, },
{ "text", true, B_OK, },
{ "text/plain", false, B_OK, },
{ "video", true, B_OK, },
{ "video/x-msvideo", false, B_OK, },
{ "unknown", true, B_OK, },
{ "unknown/mime-type", false, B_OK, },
{ "$%&./`'~*+#|!^", false, B_OK, },
{ "", false, B_BAD_VALUE, },
{ "application/", false, B_BAD_VALUE, },
{ "audio/", false, B_BAD_VALUE, },
{ "image/", false, B_BAD_VALUE, },
{ "message/", false, B_BAD_VALUE, },
{ "multipart/", false, B_BAD_VALUE, },
{ "text/", false, B_BAD_VALUE, },
{ "video/", false, B_BAD_VALUE, },
{ "unknown/", false, B_BAD_VALUE, },
{ "/gif", false, B_BAD_VALUE, },
{ "image/very/nice", false, B_BAD_VALUE, },
{ "tex t/plain", false, B_BAD_VALUE, },
{ "text/pla in", false, B_BAD_VALUE, },
{ "tex\tt/plain", false, B_BAD_VALUE, },
{ "text/pla\tin", false, B_BAD_VALUE, },
{ "tex\nt/plain", false, B_BAD_VALUE, },
{ "text/pla\nin", false, B_BAD_VALUE, },
{ "tex<t/plain", false, B_BAD_VALUE, },
{ "text/pla<in", false, B_BAD_VALUE, },
{ "tex>t/plain", false, B_BAD_VALUE, },
{ "text/pla>in", false, B_BAD_VALUE, },
{ "tex@t/plain", false, B_BAD_VALUE, },
{ "text/pla@in", false, B_BAD_VALUE, },
{ "tex,t/plain", false, B_BAD_VALUE, },
{ "text/pla,in", false, B_BAD_VALUE, },
{ "tex;t/plain", false, B_BAD_VALUE, },
{ "text/pla;in", false, B_BAD_VALUE, },
{ "tex:t/plain", false, B_BAD_VALUE, },
{ "text/pla:in", false, B_BAD_VALUE, },
{ "tex\"t/plain", false, B_BAD_VALUE, },
{ "text/pla\"in", false, B_BAD_VALUE, },
{ "tex(t/plain", false, B_BAD_VALUE, },
{ "text/pla(in", false, B_BAD_VALUE, },
{ "tex)t/plain", false, B_BAD_VALUE, },
{ "text/pla)in", false, B_BAD_VALUE, },
{ "tex[t/plain", false, B_BAD_VALUE, },
{ "text/pla[in", false, B_BAD_VALUE, },
{ "tex]t/pla]in", false, B_BAD_VALUE, },
{ "tex?t/plain", false, B_BAD_VALUE, },
{ "text/pla?in", false, B_BAD_VALUE, },
{ "tex=t/plain", false, B_BAD_VALUE, },
{ "text/pla=in", false, B_BAD_VALUE, },
{ "tex\\t/plain", false, B_BAD_VALUE, },
{ "text/pla\\in", false, B_BAD_VALUE, },
{ notTooLongType, false, B_OK, },
{ tooLongType, false, B_BAD_VALUE, },
};
int32 testCount = sizeof(tests) / sizeof(mime_type_test);
for (int32 i = 0; i < testCount; i++) {
NextSubTest();
mime_type_test &test = tests[i];
BMimeType type(test.type);
CHK(type.InitCheck() == test.error);
bool valid = (test.error == B_OK);
bool validSuper = (valid && test.super_type);
if (valid)
CHK(string(type.Type()) == test.type);
else
CHK(type.Type() == NULL);
CHK(type.IsValid() == valid);
CHK(type.IsSupertypeOnly() == validSuper);
CHK(BMimeType::IsValid(test.type) == valid);
if (valid && !validSuper) {
BMimeType super;
CHK(type.GetSupertype(&super) == B_OK);
CHK(super.InitCheck() == B_OK);
CHK(super.Contains(&type) == true);
BString typeString(test.type);
BString superString(typeString.String(),
typeString.FindFirst('/'));
CHK(superString == super.Type());
} else {
BMimeType super;
CHK(type.GetSupertype(&super) == B_BAD_VALUE);
}
for (int32 k = 0; k < testCount; k++) {
mime_type_test &test2 = tests[k];
BMimeType type2(test2.type);
CHK(type2.InitCheck() == test2.error);
bool valid2 = (test2.error == B_OK);
bool validSuper2 = (valid && test2.super_type);
bool equal = (!strcmp(test.type, test2.type));
if (valid || valid2) {
CHK((type == type2) == equal);
CHK((type == test2.type) == equal);
} else {
CHK((type == type2) == false);
CHK((type == test2.type) == false);
}
if (valid || valid2) {
if (equal)
CHK(type.Contains(&type2) == true);
else if (validSuper && valid2 && !validSuper2) {
BMimeType super2;
CHK(type2.GetSupertype(&super2) == B_OK);
bool contains = string(super2.Type()) == type.Type();
CHK(type.Contains(&type2) == contains);
} else
CHK(type.Contains(&type2) == false);
} else
CHK(type.Contains(&type2) == false);
}
}
NextSubTest();
{
BMimeType type("image/gif");
#if !TEST_R5
CHK(BMimeType::IsValid(NULL) == false);
CHK(type.GetSupertype(NULL) == B_BAD_VALUE);
CHK(type.Contains(NULL) == false);
#endif
CHK((type == NULL) == false);
}
}
class NotificationMessage {
public:
NotificationMessage(int32 which, string type, string extraType,
bool largeIcon)
: which(which), type(type), hasExtraType(true), extraType(extraType),
hasLargeIcon(true), largeIcon(largeIcon)
{
}
NotificationMessage(int32 which, string type, string extraType)
: which(which), type(type), hasExtraType(true), extraType(extraType),
hasLargeIcon(false), largeIcon(false)
{
}
NotificationMessage(int32 which, string type, bool largeIcon)
: which(which), type(type), hasExtraType(false), extraType(),
hasLargeIcon(true), largeIcon(largeIcon)
{
}
NotificationMessage(int32 which, string type)
: which(which), type(type), hasExtraType(false), extraType(),
hasLargeIcon(false), largeIcon(false)
{
}
public:
int32 which;
string type;
bool hasExtraType;
string extraType;
bool hasLargeIcon;
bool largeIcon;
};
static
void
FillAttrInfo(BMessage &info, int32 variation = 0)
{
switch (variation) {
case 0:
default:
CHK(info.AddString("attr:name", "attribute1") == B_OK);
CHK(info.AddString("attr:public_name", "Nice Attribute1") == B_OK);
CHK(info.AddInt32("attr:type", B_STRING_TYPE) == B_OK);
CHK(info.AddBool("attr:public", true) == B_OK);
CHK(info.AddBool("attr:editable", true) == B_OK);
break;
case 1:
CHK(info.AddString("attr:name", "attribute2") == B_OK);
CHK(info.AddString("attr:public_name", "Nice Attribute2") == B_OK);
CHK(info.AddInt32("attr:type", B_BOOL_TYPE) == B_OK);
CHK(info.AddBool("attr:public", false) == B_OK);
CHK(info.AddBool("attr:editable", false) == B_OK);
break;
}
}
void
MimeTypeTest::MonitoringTest()
{
CHK(fApplication != NULL);
NextSubTest();
BMessenger target(&fApplication->Handler(), fApplication);
CHK(BMimeType::StartWatching(target) == B_OK);
BMimeType type(testType);
CHK(type.InitCheck() == B_OK);
CHK(type.IsInstalled() == false);
CHK(type.Install() == B_OK);
IconHelper iconHelperLarge(B_LARGE_ICON);
IconHelper iconHelperMini(B_MINI_ICON);
CHK(type.SetIcon(iconHelperLarge.Bitmap1(), B_LARGE_ICON) == B_OK);
CHK(type.SetIcon(iconHelperMini.Bitmap1(), B_MINI_ICON) == B_OK);
CHK(type.SetPreferredApp(testTypeApp) == B_OK);
BMessage attrInfo;
FillAttrInfo(attrInfo);
CHK(type.SetAttrInfo(&attrInfo) == B_OK);
BMessage extensions;
CHK(extensions.AddString("extensions", "arg") == B_OK);
CHK(extensions.AddString("extensions", "ugh") == B_OK);
CHK(type.SetFileExtensions(&extensions) == B_OK);
CHK(type.SetLongDescription("quite short for a long description") == B_OK);
CHK(type.SetShortDescription("short description") == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperLarge.Bitmap1(),
B_LARGE_ICON) == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperMini.Bitmap1(),
B_MINI_ICON) == B_OK);
entry_ref appHintRef;
CHK(get_ref_for_path("/boot/beos/apps/StyledEdit", &appHintRef) == B_OK);
CHK(type.SetAppHint(&appHintRef) == B_OK);
const char *snifferRule = "0.5 [0:0] ('ARGH')";
CHK(type.SetSnifferRule(snifferRule) == B_OK);
{
typedef NotificationMessage NM;
NotificationMessage messages[] = {
NM(B_MIME_TYPE_CREATED, testType),
NM(B_ICON_CHANGED, testType, true),
NM(B_ICON_CHANGED, testType, false),
NM(B_PREFERRED_APP_CHANGED, testType),
NM(B_ATTR_INFO_CHANGED, testType),
NM(B_FILE_EXTENSIONS_CHANGED, testType),
NM(B_LONG_DESCRIPTION_CHANGED, testType),
NM(B_SHORT_DESCRIPTION_CHANGED, testType),
NM(B_ICON_FOR_TYPE_CHANGED, testType, "text/plain", true),
NM(B_ICON_FOR_TYPE_CHANGED, testType, "text/plain", false),
NM(B_APP_HINT_CHANGED, testType),
NM(B_SNIFFER_RULE_CHANGED, testType),
};
CheckNotificationMessages(messages, sizeof(messages) / sizeof(NM));
}
NextSubTest();
CHK(type.SetIcon(iconHelperLarge.Bitmap1(), B_LARGE_ICON) == B_OK);
CHK(type.SetIcon(iconHelperMini.Bitmap1(), B_MINI_ICON) == B_OK);
CHK(type.SetPreferredApp(testTypeApp) == B_OK);
CHK(type.SetAttrInfo(&attrInfo) == B_OK);
CHK(extensions.AddString("extensions", "arg") == B_OK);
CHK(extensions.AddString("extensions", "ugh") == B_OK);
CHK(type.SetFileExtensions(&extensions) == B_OK);
CHK(type.SetLongDescription("quite short for a long description") == B_OK);
CHK(type.SetShortDescription("short description") == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperLarge.Bitmap1(),
B_LARGE_ICON) == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperMini.Bitmap1(),
B_MINI_ICON) == B_OK);
CHK(type.SetAppHint(&appHintRef) == B_OK);
CHK(type.SetSnifferRule(snifferRule) == B_OK);
{
typedef NotificationMessage NM;
NotificationMessage messages[] = {
NM(B_ICON_CHANGED, testType, true),
NM(B_ICON_CHANGED, testType, false),
NM(B_PREFERRED_APP_CHANGED, testType),
NM(B_ATTR_INFO_CHANGED, testType),
NM(B_FILE_EXTENSIONS_CHANGED, testType),
NM(B_LONG_DESCRIPTION_CHANGED, testType),
NM(B_SHORT_DESCRIPTION_CHANGED, testType),
NM(B_ICON_FOR_TYPE_CHANGED, testType, "text/plain", true),
NM(B_ICON_FOR_TYPE_CHANGED, testType, "text/plain", false),
NM(B_APP_HINT_CHANGED, testType),
NM(B_SNIFFER_RULE_CHANGED, testType),
};
CheckNotificationMessages(messages, sizeof(messages) / sizeof(NM));
}
NextSubTest();
CHK(type.SetIcon(iconHelperLarge.Bitmap2(), B_LARGE_ICON) == B_OK);
CHK(type.SetIcon(iconHelperMini.Bitmap2(), B_MINI_ICON) == B_OK);
CHK(type.SetPreferredApp("application/x-vnd.Be-STEE") == B_OK);
BMessage attrInfo2;
FillAttrInfo(attrInfo2, 1);
CHK(type.SetAttrInfo(&attrInfo2) == B_OK);
CHK(extensions.AddString("extensions", "uff") == B_OK);
CHK(extensions.AddString("extensions", "err") == B_OK);
CHK(type.SetFileExtensions(&extensions) == B_OK);
CHK(type.SetLongDescription("not that short description") == B_OK);
CHK(type.SetShortDescription("pretty short description") == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperLarge.Bitmap2(),
B_LARGE_ICON) == B_OK);
CHK(type.SetIconForType("text/plain", NULL,
B_LARGE_ICON) == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperMini.Bitmap2(),
B_MINI_ICON) == B_OK);
entry_ref appHintRef2;
CHK(get_ref_for_path("/boot/beos/apps/NetPositive", &appHintRef2) == B_OK);
CHK(type.SetAppHint(&appHintRef2) == B_OK);
const char *snifferRule2 = "0.7 [0:5] ('YEAH!')";
CHK(type.SetSnifferRule(snifferRule2) == B_OK);
CHK(type.Delete() == B_OK);
{
typedef NotificationMessage NM;
NotificationMessage messages[] = {
NM(B_ICON_CHANGED, testType, true),
NM(B_ICON_CHANGED, testType, false),
NM(B_PREFERRED_APP_CHANGED, testType),
NM(B_ATTR_INFO_CHANGED, testType),
NM(B_FILE_EXTENSIONS_CHANGED, testType),
NM(B_LONG_DESCRIPTION_CHANGED, testType),
NM(B_SHORT_DESCRIPTION_CHANGED, testType),
NM(B_ICON_FOR_TYPE_CHANGED, testType, "text/plain", true),
NM(B_ICON_FOR_TYPE_CHANGED, testType, "text/plain", true),
NM(B_ICON_FOR_TYPE_CHANGED, testType, "text/plain", false),
NM(B_APP_HINT_CHANGED, testType),
NM(B_SNIFFER_RULE_CHANGED, testType),
NM(B_MIME_TYPE_DELETED, testType),
};
CheckNotificationMessages(messages, sizeof(messages) / sizeof(NM));
}
CHK(BMimeType::StopWatching(target) == B_OK);
CHK(type.InitCheck() == B_OK);
CHK(type.IsInstalled() == false);
CHK(type.Install() == B_OK);
CHK(type.SetIcon(iconHelperLarge.Bitmap1(), B_LARGE_ICON) == B_OK);
CHK(type.SetIcon(iconHelperMini.Bitmap1(), B_MINI_ICON) == B_OK);
CHK(type.SetPreferredApp(testTypeApp) == B_OK);
CHK(type.SetAttrInfo(&attrInfo) == B_OK);
CHK(extensions.AddString("extensions", "arg") == B_OK);
CHK(extensions.AddString("extensions", "ugh") == B_OK);
CHK(type.SetFileExtensions(&extensions) == B_OK);
CHK(type.SetLongDescription("quite short for a long description") == B_OK);
CHK(type.SetShortDescription("short description") == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperLarge.Bitmap1(),
B_LARGE_ICON) == B_OK);
CHK(type.SetIconForType("text/plain", iconHelperMini.Bitmap1(),
B_MINI_ICON) == B_OK);
CHK(type.SetAppHint(&appHintRef) == B_OK);
CHK(type.SetSnifferRule(snifferRule) == B_OK);
CHK(type.Delete() == B_OK);
{
CheckNotificationMessages(NULL, 0);
}
NextSubTest();
CHK(type.InitCheck() == B_OK);
CHK(type.IsInstalled() == false);
CHK(type.Install() == B_OK);
BMessenger target2(fApplication);
CHK(target2.IsValid() == true);
BMessenger target3("application/does-not_exist");
CHK(target3.IsValid() == false);
#if !TEST_R5
CHK(BMimeType::StartWatching(target3) == B_BAD_VALUE);
#endif
CHK(BMimeType::StartWatching(target) == B_OK);
#if !TEST_R5
CHK(BMimeType::StopWatching(target3) == B_BAD_VALUE);
#endif
CHK(BMimeType::StopWatching(target2) != B_OK);
CHK(BMimeType::StopWatching(target) == B_OK);
CHK(type.Delete() == B_OK);
}
void
MimeTypeTest::CheckNotificationMessages(const NotificationMessage *messages,
int32 count)
{
snooze(100000);
if (fApplication) {
BMessageQueue &queue = fApplication->Handler().Queue();
CPPUNIT_ASSERT( queue.Lock() );
try {
int32 messageNum = 0;
while (BMessage *_message = queue.NextMessage()) {
BMessage message(*_message);
delete _message;
CPPUNIT_ASSERT( messageNum < count );
const NotificationMessage &entry = messages[messageNum];
CPPUNIT_ASSERT( message.what == B_META_MIME_CHANGED );
int32 which;
CPPUNIT_ASSERT( message.FindInt32("be:which", &which)
== B_OK );
CPPUNIT_ASSERT( entry.which == which );
const char *type;
CPPUNIT_ASSERT( message.FindString("be:type", &type) == B_OK );
CPPUNIT_ASSERT( entry.type == type );
const char *extraType;
if (entry.hasExtraType) {
CPPUNIT_ASSERT( message.FindString("be:extra_type",
&extraType) == B_OK);
CPPUNIT_ASSERT( entry.extraType == extraType );
} else {
CPPUNIT_ASSERT( message.FindString("be:extra_type",
&extraType) == B_NAME_NOT_FOUND);
}
bool largeIcon;
if (entry.hasLargeIcon) {
CPPUNIT_ASSERT( message.FindBool("be:large_icon",
&largeIcon) == B_OK);
CPPUNIT_ASSERT( entry.largeIcon == largeIcon );
} else {
CPPUNIT_ASSERT( message.FindBool("be:large_icon",
&largeIcon) == B_NAME_NOT_FOUND);
}
messageNum++;
}
CPPUNIT_ASSERT( messageNum == count );
} catch (CppUnit::Exception exception) {
queue.Unlock();
throw exception;
}
queue.Unlock();
}
}
class MimeInfoTestFile {
public:
MimeInfoTestFile(string name, string type, const void *data = NULL,
int32 size = -1)
: name(name),
type(type),
data(NULL),
size(0)
{
if (data) {
if (size == -1)
this->size = strlen((const char*)data) + 1;
else
this->size = size;
this->data = new char[this->size];
memcpy(this->data, data, this->size);
}
}
~MimeInfoTestFile()
{
delete[] data;
}
status_t Create()
{
BFile file(name.c_str(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
status_t error = file.InitCheck();
if (error == B_OK && data) {
ssize_t written = file.Write(data, size);
if (written < 0)
error = written;
else if (written != size)
error = B_ERROR;
}
return error;
}
status_t Delete()
{
return BEntry(name.c_str()).Remove();
}
string name;
string type;
char *data;
int32 size;
};
void
MimeTypeTest::UpdateMimeInfoTest()
{
execCommand(string("mkdir ") + testDir + "/subdir1 "
+ testDir + "/subdir2 "
+ testDir + "/subdir2/subsubdir1");
MimeInfoTestFile files[] = {
MimeInfoTestFile(string(testDir) + "/file1.cpp", "text/x-source-code"),
MimeInfoTestFile(string(testDir) + "/subdir1/file1.gif", "image/gif"),
MimeInfoTestFile(string(testDir) + "/subdir2/subsubdir1/file1",
"text/html", "<html>\n<body>\n</body></html>\n")
};
int fileCount = sizeof(files) / sizeof(MimeInfoTestFile);
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
MimeInfoTestFile &file = files[i];
CHK(file.Create() == B_OK);
CHK(update_mime_info(file.name.c_str(), false, true, false) == B_OK);
BNode node(file.name.c_str());
CHK(node.InitCheck() == B_OK);
BString type;
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
node.Unset();
CHK(type == file.type.c_str());
CHK(file.Delete() == B_OK);
CHK(file.Create() == B_OK);
CHK(update_mime_info(file.name.c_str(), true, true, false) == B_OK);
CHK(node.SetTo(file.name.c_str()) == B_OK);
type = "";
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
node.Unset();
CHK(type == file.type.c_str());
CHK(file.Delete() == B_OK);
}
const bigtime_t kSnoozeTime = 500000;
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
MimeInfoTestFile &file = files[i];
CHK(file.Create() == B_OK);
CHK(update_mime_info(file.name.c_str(), false, false, false) == B_OK);
snooze(kSnoozeTime);
BNode node(file.name.c_str());
CHK(node.InitCheck() == B_OK);
BString type;
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
node.Unset();
CHK(type == file.type.c_str());
CHK(file.Delete() == B_OK);
CHK(file.Create() == B_OK);
CHK(update_mime_info(file.name.c_str(), true, false, false) == B_OK);
snooze(kSnoozeTime);
CHK(node.SetTo(file.name.c_str()) == B_OK);
type = "";
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
node.Unset();
CHK(type == file.type.c_str());
CHK(file.Delete() == B_OK);
}
#if TEST_OBOS
for (int32 i = 0; i < fileCount; i++) {
MimeInfoTestFile &file = files[i];
CHK(file.Create() == B_OK);
BNode node(file.name.c_str());
CHK(node.InitCheck() == B_OK);
BString type("text/plain");
CHK(node.WriteAttrString("BEOS:TYPE", &type) == B_OK);
CHK(update_mime_info(file.name.c_str(), false, true, false) == B_OK);
type = "";
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
CHK(type == "text/plain");
CHK(update_mime_info(file.name.c_str(), false, true, true) == B_OK);
type = "";
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
node.Unset();
CHK(type == file.type.c_str());
CHK(file.Delete() == B_OK);
}
#endif
NextSubTest();
for (int32 i = 0; i < fileCount; i++) {
MimeInfoTestFile &file = files[i];
CHK(file.Create() == B_OK);
}
CHK(update_mime_info(testDir, false, true, false) == B_OK);
for (int32 i = 0; i < fileCount; i++) {
MimeInfoTestFile &file = files[i];
BNode node(file.name.c_str());
CHK(node.InitCheck() == B_OK);
BString type;
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_ENTRY_NOT_FOUND);
}
for (int32 i = 0; i < fileCount; i++) {
MimeInfoTestFile &file = files[i];
CHK(file.Delete() == B_OK);
CHK(file.Create() == B_OK);
}
CHK(update_mime_info(testDir, true, true, false) == B_OK);
for (int32 i = 0; i < fileCount; i++) {
MimeInfoTestFile &file = files[i];
BNode node(file.name.c_str());
CHK(node.InitCheck() == B_OK);
BString type;
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
node.Unset();
CHK(type == file.type.c_str());
}
for (int32 i = 0; i < fileCount; i++) {
MimeInfoTestFile &file = files[i];
CHK(file.Delete() == B_OK);
}
NextSubTest();
BEntry entry(files[0].name.c_str());
CHK(entry.InitCheck() == B_OK);
CHK(entry.Exists() == false);
CHK(update_mime_info(files[0].name.c_str(), false, true, false) == B_OK);
}
static
status_t
WriteStringAttr(BNode &node, string name, string _value)
{
BString value(_value.c_str());
return node.WriteAttrString(name.c_str(), &value);
}
const uint32 MINI_ICON_TYPE = 'MICN';
const uint32 LARGE_ICON_TYPE = 'ICON';
class AppMimeTestFile {
public:
AppMimeTestFile(string name, string type, string signature,
string snifferRule,
const void *miniIcon = NULL, const void *largeIcon = NULL)
: name(name),
type(type),
signature(signature),
snifferRule(snifferRule),
miniIcon(NULL),
largeIcon(NULL)
{
SetMiniIcon(miniIcon);
SetLargeIcon(largeIcon);
}
~AppMimeTestFile()
{
SetMiniIcon(NULL);
SetLargeIcon(NULL);
}
void SetMiniIcon(const void *icon)
{
if (miniIcon) {
delete[] miniIcon;
miniIcon = NULL;
}
if (icon) {
miniIcon = new char[256];
memcpy(miniIcon, icon, 256);
}
}
void SetLargeIcon(const void *icon)
{
if (largeIcon) {
delete[] largeIcon;
largeIcon = NULL;
}
if (icon) {
largeIcon = new char[1024];
memcpy(largeIcon, icon, 1024);
}
}
status_t Create(bool setAttributes, bool setResources)
{
BFile file(name.c_str(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
status_t error = file.InitCheck();
if (error == B_OK && setAttributes) {
if (type.length() > 0)
error = WriteStringAttr(file, "BEOS:TYPE", type);
if (error == B_OK)
error = WriteStringAttr(file, "BEOS:APP_SIG", signature);
if (error == B_OK)
error = WriteStringAttr(file, "BEOS:SNIFF_RULE", snifferRule);
if (error == B_OK && miniIcon) {
ssize_t written = file.WriteAttr("BEOS:M:STD_ICON",
MINI_ICON_TYPE, 0, miniIcon,
256);
if (written < 0)
error = written;
else if (written != 256)
error = B_ERROR;
}
if (error == B_OK && largeIcon) {
ssize_t written = file.WriteAttr("META:L:STD_ICON",
LARGE_ICON_TYPE, 0, largeIcon,
1024);
if (written < 0)
error = written;
else if (written != 1024)
error = B_ERROR;
}
}
if (error == B_OK && setResources) {
BResources resources;
error = resources.SetTo(&file, true);
if (error == B_OK && type.length() > 0) {
error = resources.AddResource(B_STRING_TYPE, 2, type.c_str(),
type.length() + 1, "BEOS:TYPE");
}
if (error == B_OK) {
error = resources.AddResource(B_STRING_TYPE, 1,
signature.c_str(),
signature.length() + 1,
"BEOS:APP_SIG");
}
if (error == B_OK && miniIcon) {
error = resources.AddResource(MINI_ICON_TYPE, 101, miniIcon,
256, "BEOS:M:STD_ICON");
}
if (error == B_OK) {
BMessage msg;
char *buffer = NULL;
error = msg.AddString("types", "text/x-email");
if (!error)
error = msg.AddString("types", "video/mpeg");
if (!error) {
buffer = new char[msg.FlattenedSize()];
if (!buffer)
error = B_NO_MEMORY;
}
if (!error)
error = msg.Flatten(buffer, msg.FlattenedSize());
if (!error)
error = resources.AddResource(B_MESSAGE_TYPE, 1, buffer,
msg.FlattenedSize(), "BEOS:FILE_TYPES");
delete [] buffer;
}
}
return error;
}
status_t Delete(bool deleteMimeType)
{
status_t error = BEntry(name.c_str()).Remove();
if (error == B_OK && deleteMimeType) {
BMimeType type;
error = type.SetTo(signature.c_str());
if (error == B_OK && deleteMimeType && type.IsInstalled())
error = type.Delete();
}
return error;
}
string name;
string type;
string signature;
string snifferRule;
char *miniIcon;
char *largeIcon;
};
static
void
CheckAppMetaMime(AppMimeTestFile &file)
{
BMimeType type;
CHK(type.SetTo(file.signature.c_str()) == B_OK);
CHK(type.IsInstalled() == true);
char shortDescription[B_MIME_TYPE_LENGTH + 1];
CHK(type.GetShortDescription(shortDescription) == B_OK);
BPath path(file.name.c_str(), NULL, true);
CHK(string(path.Leaf()) == shortDescription);
char preferredApp[B_MIME_TYPE_LENGTH + 1];
CHK(type.GetPreferredApp(preferredApp) == B_OK);
CHK(file.signature == preferredApp);
BNode typeFile;
string typeFilename(string(mimeDatabaseDir) + "/" + file.signature);
CHK(typeFile.SetTo(typeFilename.c_str()) == B_OK);
char filePath[B_PATH_NAME_LENGTH + 1];
CHK(typeFile.ReadAttr("META:PPATH", B_STRING_TYPE, 0, filePath,
B_PATH_NAME_LENGTH + 1) > 0);
CHK(path == filePath);
if (file.miniIcon) {
BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
CHK(type.GetIcon(&icon, B_MINI_ICON) == B_OK);
CHK(memcmp(icon.Bits(), file.miniIcon, 256) == 0);
}
}
void
MimeTypeTest::CreateAppMetaMimeTest()
{
char miniIcon1[256];
char miniIcon2[256];
for (int ch = 0; ch < 256; ch++) {
miniIcon1[ch] = ch;
miniIcon2[ch] = 255-ch;
}
char largeIcon1[1024];
char largeIcon2[1024];
for (int i = 0; i < 1024; i++) {
char ch = i % 256;
largeIcon1[i] = ch;
largeIcon2[i] = 255-ch;
}
NextSubTest();
execCommand(string("mkdir ") + testDir + "/subdir1 "
+ testDir + "/subdir2 "
+ testDir + "/subdir2/subsubdir1");
AppMimeTestFile files[] = {
AppMimeTestFile(string(testDir) + "/file1",
"",
"application/x-vnd.obos.mime.test.test1",
"0.0 ('abc')",
miniIcon1,
NULL),
AppMimeTestFile(string(testDir) + "/file2",
"text/x-source-code",
"application/x-vnd.obos.mime.test.test2",
"0.0 ('xyz')",
miniIcon2,
largeIcon2),
AppMimeTestFile(string(testDir) + "/file3",
"application/x-vnd.Be-elfexecutable",
"application/x-vnd.obos.mime.test.test3",
"0.0 ('rst')",
NULL,
largeIcon1),
};
const int fileCount = sizeof(files) / sizeof(AppMimeTestFile);
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
AppMimeTestFile &file = files[i];
CHK(file.Create(true, true) == B_OK);
CHK(create_app_meta_mime(file.name.c_str(), false, true, false)
== B_OK);
CheckAppMetaMime(file);
CHK(file.Delete(true) == B_OK);
}
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
AppMimeTestFile &file = files[i];
CHK(file.Create(true, false) == B_OK);
CHK(create_app_meta_mime(file.name.c_str(), false, true, false)
== B_OK);
CheckAppMetaMime(file);
CHK(file.Delete(true) == B_OK);
}
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
AppMimeTestFile &file = files[i];
CHK(file.Create(false, true) == B_OK);
CHK(create_app_meta_mime(file.name.c_str(), false, true, false)
== B_OK);
BMimeType type;
CHK(type.SetTo(file.signature.c_str()) == B_OK);
CHK(type.IsInstalled() == false);
CHK(file.Delete(false) == B_OK);
}
const bigtime_t kSnoozeTime = 500000;
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
AppMimeTestFile &file = files[i];
CHK(file.Create(true, true) == B_OK);
CHK(create_app_meta_mime(file.name.c_str(), false, false, false)
== B_OK);
snooze(kSnoozeTime);
CheckAppMetaMime(file);
CHK(file.Delete(true) == B_OK);
}
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
AppMimeTestFile &file = files[i];
CHK(file.Create(true, false) == B_OK);
CHK(create_app_meta_mime(file.name.c_str(), false, false, false)
== B_OK);
snooze(kSnoozeTime);
CheckAppMetaMime(file);
CHK(file.Delete(true) == B_OK);
}
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
AppMimeTestFile &file = files[i];
CHK(file.Create(false, true) == B_OK);
CHK(create_app_meta_mime(file.name.c_str(), false, false, false)
== B_OK);
snooze(kSnoozeTime);
BMimeType type;
CHK(type.SetTo(file.signature.c_str()) == B_OK);
CHK(type.IsInstalled() == false);
CHK(file.Delete(false) == B_OK);
}
#if !TEST_R5
{
char icon1[256];
char icon2[256];
memset(icon1, 1, 256);
memset(icon2, 2, 256);
AppMimeTestFile file1(string(testDir) + "/file1",
"application/x-vnd.Be-elfexecutable",
"application/x-vnd.obos.mime.test.test1",
icon1);
AppMimeTestFile file2(string(testDir) + "/file1",
"application/x-vnd.Be-elfexecutable",
"application/x-vnd.obos.mime.test.test1",
icon2);
CHK(file1.Create(true, true) == B_OK);
CHK(create_app_meta_mime(file1.name.c_str(), false, true, false)
== B_OK);
CheckAppMetaMime(file1);
CHK(file2.Create(true, true) == B_OK);
CHK(create_app_meta_mime(file2.name.c_str(), false, true, false)
== B_OK);
CheckAppMetaMime(file1);
CHK(create_app_meta_mime(file2.name.c_str(), false, true, true)
== B_OK);
CheckAppMetaMime(file2);
CHK(file2.Delete(true) == B_OK);
}
{
char icon1[256];
char icon2[256];
memset(icon1, 1, 256);
memset(icon2, 2, 256);
AppMimeTestFile file1(string(testDir) + "/file1",
"application/x-vnd.Be-elfexecutable",
"application/x-vnd.obos.mime.test.test1",
icon1);
AppMimeTestFile file2(string(testDir) + "/file2",
"application/x-vnd.Be-elfexecutable",
"application/x-vnd.obos.mime.test.test1",
icon2);
CHK(file1.Create(true, true) == B_OK);
CHK(create_app_meta_mime(file1.name.c_str(), false, true, false)
== B_OK);
CheckAppMetaMime(file1);
CHK(file2.Create(true, true) == B_OK);
CHK(create_app_meta_mime(file2.name.c_str(), false, true, false)
== B_OK);
CheckAppMetaMime(file1);
CHK(create_app_meta_mime(file2.name.c_str(), false, true, true)
== B_OK);
CheckAppMetaMime(file2);
CHK(file1.Delete(true) == B_OK);
CHK(file2.Delete(true) == B_OK);
}
#endif
NextSubTest();
CHK(files[0].Create(false, false) == B_OK);
CHK(create_app_meta_mime(files[0].name.c_str(), false, true, false)
== B_OK);
CHK(files[0].Delete(false) == B_OK);
CHK(create_app_meta_mime(files[0].name.c_str(), false, true, false)
== B_OK);
}
static
void
CheckIconData(const char *device, int32 iconSize, const void* data)
{
int fd = open(device, O_RDONLY);
CHK(fd != -1);
char buffer[1024];
device_icon iconData = {
iconSize,
buffer
};
int error = ioctl(fd, B_GET_ICON, &iconData);
CHK(close(fd) == 0);
CHK(error == 0);
CHK(memcmp(data, buffer, iconSize * iconSize) == 0);
}
void
MimeTypeTest::GetDeviceIconTest()
{
struct test_case {
const char *path;
bool valid;
} testCases[] = {
{ "/dev/zero", false },
{ "/boot", true },
{ "/boot/home", false }
};
const int testCaseCount = sizeof(testCases) / sizeof(test_case);
for (int32 i = 0; i < testCaseCount; i++) {
NextSubTest();
test_case &testCase = testCases[i];
fs_info info;
const char *deviceName = testCase.path;
if (testCase.valid) {
dev_t dev = dev_for_path(testCase.path);
CHK(dev > 0);
CHK(fs_stat_dev(dev, &info) == 0);
deviceName = info.device_name;
}
const int32 iconSizes[] = { 16, 32, 20 };
const bool validSizes[] = { true, true, false };
const int sizeCount = sizeof(iconSizes) / sizeof(int32);
for (int32 k = 0; k < sizeCount; k++) {
int32 size = iconSizes[k];
bool valid = testCase.valid && validSizes[k];
char buffer[1024];
if (valid) {
CHK(get_device_icon(deviceName, buffer, size) == B_OK);
CheckIconData(deviceName, size, buffer);
#if !TEST_R5
CHK(get_device_icon(deviceName, NULL, size) == B_BAD_VALUE);
#endif
} else
CHK(get_device_icon(deviceName, buffer, size) != B_OK);
}
}
}
void
MimeTypeTest::SnifferRuleTest()
{
struct test_case {
const char *rule;
const char *error;
} testCases[] = {
{ "1.0 (\"ABCD\")", NULL },
{ "1.0 ('ABCD')", NULL },
{ " 1.0 ('ABCD') ", NULL },
{ "0.8 [0:3] ('ABCDEFG' | 'abcdefghij')", NULL },
{ "0.5([10]'ABCD'|[17]'abcd'|[13]'EFGH')", NULL } ,
{ "0.5 \n [0:3] \t ('ABCD' \n | 'abcd' | 'EFGH')", NULL },
{ "0.8 [ 0 : 3 ] ('ABCDEFG' | 'abcdefghij')", NULL },
{ "0.8 [0:3] ('ABCDEFG' & 'abcdefg')", NULL },
#if TEST_R5
{ "1.0 ('ABCD') | ('EFGH')", NULL },
{ "1.0 [0:3] ('ABCD') | [2:4] ('EFGH')", NULL },
#else
{ "1.0 ('ABCD') | ('EFGH')", "Sniffer pattern error: missing pattern" },
{ "1.0 [0:3] ('ABCD') | [2:4] ('EFGH')", "Sniffer pattern error: missing pattern" },
#endif
{ "0.8 [0:3] (\\077Mkl0x34 & 'abcdefgh')", NULL },
{ "0.8 [0:3] (\\077034 & 'abcd')", NULL },
{ "0.8 [0:3] (\\077\\034 & 'ab')", NULL },
{ "0.8 [0:3] (\\77\\034 & 'ab')", NULL },
{ "0.8 [0:3] (\\7 & 'a')", NULL },
{ "0.8 [0:3] (\"\\17\" & 'a')", NULL },
{ "0.8 [0:3] ('\\17' & 'a')", NULL },
{ "0.8 [0:3] (\\g & 'a')", NULL },
{ "0.8 [0:3] (\\g&\\b)", NULL },
{ "0.8 [0:3] (\\g\\&b & 'abc')", NULL },
{ "0.8 [0:3] (0x3457 & 'ab')", NULL },
{ "0.8 [0:3] (0xA4b7 & 'ab')", NULL },
{ "0.8 [0:3] ('ab\"' & 'abc')", NULL },
{ "0.8 [0:3] (\"ab\\\"\" & 'abc')", NULL },
{ "0.8 [0:3] (\"ab\\A\" & 'abc')", NULL },
{ "0.8 [0:3] (\"ab'\" & 'abc')", NULL },
{ "0.8 [0:3] (\"ab\\\\\" & 'abc')", NULL },
{ "0.8 [-5:-3] (\"abc\" & 'abc')", NULL },
#if TEST_R5
{ "0.8 [5:3] (\"abc\" & 'abc')", NULL },
#else
{ "0.8 [5:3] (\"abc\" & 'abc')", "Sniffer Parser Error -- Invalid range: [5:3]" },
#endif
{ "1.0 ('ABCD')", NULL },
{ ".2 ('ABCD')", NULL },
{ "0. ('ABCD')", NULL },
{ "1 ('ABCD')", NULL },
{ "+1 ('ABCD')", NULL },
#if TEST_R5
{ "1E25 ('ABCD')", NULL },
{ "1e25 ('ABCD')", NULL },
#else
{ "1E25 ('ABCD')", "Sniffer pattern error: invalid priority" },
{ "1e25 ('ABCD')", "Sniffer pattern error: invalid priority" },
#endif
#if TEST_R5
{ "1e-3 ('ABCD')", "Sniffer pattern error: missing pattern" },
#else
{ "1e-3 ('ABCD')", NULL },
#endif
{ "+.003e2 ('ABCD')", NULL },
#if TEST_R5
{ "-123e-9999999999 ('ABCD')", "Sniffer pattern error: bad token" },
#else
{ "-123e-9999999999 ('ABCD')", NULL },
#endif
{ "0.0 ('')",
"Sniffer pattern error: illegal empty pattern" },
{ "('ABCD')",
"Sniffer pattern error: match level expected" },
{ "[0:3] ('ABCD')",
"Sniffer pattern error: match level expected" },
{ "0.8 [0:3] ( | 'abcdefghij')",
"Sniffer pattern error: missing pattern" },
{ "0.8 [0:3] ('ABCDEFG' | )",
"Sniffer pattern error: missing pattern" },
{ "[0:3] ('ABCD')",
"Sniffer pattern error: match level expected" },
{ "1.0 (ABCD')",
#if TEST_R5
"Sniffer pattern error: misplaced single quote"
#else
"Sniffer pattern error: invalid character 'A'"
#endif
},
{ "1.0 ('ABCD)",
#if TEST_R5
"Sniffer pattern error: unterminated rule"
#else
"Sniffer pattern error: unterminated single-quoted string"
#endif
},
{ "1.0 (ABCD)",
#if TEST_R5
"Sniffer pattern error: missing pattern"
#else
"Sniffer pattern error: invalid character 'A'"
#endif
},
{ "1.0 (ABCD 'ABCD')",
#if TEST_R5
"Sniffer pattern error: missing pattern"
#else
"Sniffer pattern error: invalid character 'A'"
#endif
},
{ "1.0 'ABCD')",
#if TEST_R5
"Sniffer pattern error: missing pattern"
#else
"Sniffer pattern error: missing pattern"
#endif
},
{ "1.0 ('ABCD'",
"Sniffer pattern error: unterminated rule" },
{ "1.0 'ABCD'",
#if TEST_R5
"Sniffer pattern error: missing sniff pattern"
#else
"Sniffer pattern error: missing pattern"
#endif
},
{ "0.5 [0:3] ('ABCD' | 'abcd' | [13] 'EFGH')",
"Sniffer pattern error: missing pattern" },
{ "0.5('ABCD'|'abcd'|[13]'EFGH')",
"Sniffer pattern error: missing pattern" },
{ "0.5[0:3]([10]'ABCD'|[17]'abcd'|[13]'EFGH')",
"Sniffer pattern error: missing pattern" },
{ "0.8 [0x10:3] ('ABCDEFG' | 'abcdefghij')",
"Sniffer pattern error: pattern offset expected" },
{ "0.8 [0:A] ('ABCDEFG' | 'abcdefghij')",
#if TEST_R5
"Sniffer pattern error: pattern range end expected"
#else
"Sniffer pattern error: invalid character 'A'"
#endif
},
{ "0.8 [0:3] ('ABCDEFG' & 'abcdefghij')",
"Sniffer pattern error: pattern and mask lengths do not match" },
{ "0.8 [0:3] ('ABCDEFG' & 'abcdefg' & 'xyzwmno')",
#if TEST_R5
"Sniffer pattern error: unterminated rule"
#else
"Sniffer pattern error: expecting '|', ')', or possibly '&'"
#endif
},
{ "0.8 [0:3] (\\g&b & 'a')",
#if TEST_R5
"Sniffer pattern error: missing mask"
#else
"Sniffer pattern error: invalid character 'b'"
#endif
},
{ "0.8 [0:3] (\\19 & 'a')",
"Sniffer pattern error: pattern and mask lengths do not match" },
{ "0.8 [0:3] (0x345 & 'ab')",
"Sniffer pattern error: bad hex literal" },
{ "0.8 [0:3] (0x3457M & 'abc')",
#if TEST_R5
"Sniffer pattern error: expecting '|' or '&'"
#else
"Sniffer pattern error: invalid character 'M'"
#endif
},
{ "0.8 [0:3] (0x3457\\7 & 'abc')",
#if TEST_R5
"Sniffer pattern error: expecting '|' or '&'"
#else
"Sniffer pattern error: expecting '|', ')', or possibly '&'"
#endif
},
#if !TEST_R5
{ "\x03 ", "Sniffer pattern error: invalid character '\x03'" },
{ "\"blah", "Sniffer pattern error: unterminated double-quoted string" },
{ "0xThisIsNotAHexCode", "Sniffer pattern error: incomplete hex code" },
{ "0xAndNeitherIsThis:-)", "Sniffer pattern error: bad hex literal" },
{ ".NotAFloat", "Sniffer pattern error: incomplete floating point number" },
{ "-NotANumber", "Sniffer pattern error: incomplete signed number" },
{ "+NotANumber", "Sniffer pattern error: incomplete signed number" },
{ "0.0e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "1.0e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ ".0e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "0e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "1e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1.e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1.e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1.0e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1.0e", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "0.0e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "1.0e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ ".0e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "0e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "1e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1.e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1.e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1.0e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1.0e-", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "0.0e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "1.0e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ ".0e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "0e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "1e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1.e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1.e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "-1.0e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "+1.0e+", "Sniffer pattern error: incomplete extended-notation floating point number" },
{ "\\11\\", "Sniffer pattern error: incomplete escape sequence" },
{ "\"Escape!! \\", "Sniffer pattern error: incomplete escape sequence" },
{ "'Escape!! \\", "Sniffer pattern error: incomplete escape sequence" },
{ "\\x", "Sniffer pattern error: incomplete escaped hex code" },
{ "\\xNotAHexCode", "Sniffer pattern error: incomplete escaped hex code" },
{ "\\xAlsoNotAHexCode", "Sniffer pattern error: incomplete escaped hex code" },
{ "\\x0", "Sniffer pattern error: incomplete escaped hex code" },
{ "1.0 (\\377)", NULL },
{ "\\400", "Sniffer pattern error: invalid octal literal (octals must be between octal 0 and octal 377 inclusive)" },
{ "\\777", "Sniffer pattern error: invalid octal literal (octals must be between octal 0 and octal 377 inclusive)" },
{ "1.0 (\\800)", NULL },
{ NULL, "Sniffer pattern error: NULL pattern" },
{ "-2", "Sniffer pattern error: invalid priority" },
{ "+2", "Sniffer pattern error: invalid priority" },
{ "1.0", "Sniffer pattern error: missing expression" },
#endif
#if TEST_R5
{ "1E-25 ('ABCD')", "Sniffer pattern error: missing pattern" },
#else
#endif
};
const int testCaseCount = sizeof(testCases) / sizeof(test_case);
BMimeType type;
CHK(type.SetTo(testType) == B_OK);
CHK(type.Install() == B_OK);
for (int32 i = 0; i < testCaseCount; i++) {
NextSubTest();
test_case &testCase = testCases[i];
BString parseError;
status_t error = BMimeType::CheckSnifferRule(testCase.rule,
&parseError);
if (testCase.error == NULL) {
if (error != B_OK)
printf("\nerror:\n%s\n", parseError.String());
CHK(error == B_OK);
CHK(type.SetSnifferRule(testCase.rule) == B_OK);
BString rule;
CHK(type.GetSnifferRule(&rule) == B_OK);
CHK(rule == testCase.rule);
} else {
CHK(error == (testCase.rule ? B_BAD_MIME_SNIFFER_RULE : B_BAD_VALUE));
CHK(parseError.FindLast(testCase.error) >= 0);
#if TEST_R5
CHK(type.SetSnifferRule(testCase.rule) == B_BAD_MIME_SNIFFER_RULE);
#else
if (testCase.rule)
CHK(type.SetSnifferRule(testCase.rule) == B_BAD_MIME_SNIFFER_RULE);
else
CHK(type.SetSnifferRule(testCase.rule) == B_OK);
#endif
}
}
NextSubTest();
BString parseError;
CHK(BMimeType::CheckSnifferRule("0.0 ('')", NULL)
== B_BAD_MIME_SNIFFER_RULE);
#if !TEST_R5
CHK(BMimeType::CheckSnifferRule(NULL, &parseError) == B_BAD_VALUE);
CHK(BMimeType::CheckSnifferRule(NULL, NULL) == B_BAD_VALUE);
CHK(type.GetSnifferRule(NULL) == B_BAD_VALUE);
#endif
BString rule;
NextSubTest();
#if TEST_R5
CHK(type.IsInstalled() == true);
CHK(type.SetSnifferRule(NULL) == B_OK);
CHK(type.GetSnifferRule(&rule) == B_ENTRY_NOT_FOUND);
#else
CHK(type.IsInstalled() == true);
if (type.GetSnifferRule(&rule) == B_ENTRY_NOT_FOUND)
CHK(type.SetSnifferRule("0.0 ('abc')") == B_OK);
CHK(type.GetSnifferRule(&rule) == B_OK);
CHK(type.SetSnifferRule(NULL) == B_OK);
CHK(type.GetSnifferRule(&rule) == B_ENTRY_NOT_FOUND);
CHK(type.SetSnifferRule(NULL) == B_ENTRY_NOT_FOUND);
#endif
CHK(type.Delete() == B_OK);
CHK(type.GetSnifferRule(&rule) == B_ENTRY_NOT_FOUND);
CHK(type.SetSnifferRule("0.0 ('ABC')") == B_OK);
#if TEST_R5
CHK(type.GetSnifferRule(&rule) == B_ENTRY_NOT_FOUND);
#else
CHK(type.GetSnifferRule(&rule) == B_OK);
#endif
type.Unset();
CHK(type.GetSnifferRule(&rule) != B_OK);
CHK(type.SetSnifferRule("0.0 ('ABC')") != B_OK);
}
class SniffingTestFile {
public:
SniffingTestFile(string name, string extensionType, string contentType,
const void *data = NULL, int32 size = -1, string metaType = "")
: name(name)
, extensionType(extensionType)
, contentType(contentType)
, data(NULL)
, size(0)
, metaType(metaType)
{
if (this->extensionType == "")
this->extensionType = "application/octet-stream";
if (this->contentType == "")
this->contentType = "application/octet-stream";
if (data) {
if (size == -1)
this->size = strlen((const char*)data) + 1;
else
this->size = size;
this->data = new char[this->size];
memcpy(this->data, data, this->size);
}
}
~SniffingTestFile()
{
delete[] data;
}
status_t Create()
{
BFile file(name.c_str(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
ssize_t error = file.InitCheck();
if (error == B_OK && data) {
ssize_t written = file.Write(data, size);
if (written < 0)
error = written;
else if (written != size)
error = B_ERROR;
}
if (!error && metaType.length() > 0) {
error = file.WriteAttr("META:TYPE", B_STRING_TYPE, 0, metaType.c_str(),
metaType.length()+1);
error = error == (ssize_t)(metaType.length()+1) ? B_OK : error;
}
return error;
}
status_t Delete()
{
return BEntry(name.c_str()).Remove();
}
string name;
string extensionType;
string contentType;
char *data;
int32 size;
string metaType;
};
void
MimeTypeTest::SniffingTest()
{
{
BMimeType type;
CHK(type.SetTo(testType) == B_OK);
CHK(type.Install() == B_OK);
CHK(type.SetSnifferRule("0.5 [0:1] ('ABCD_EFGH' & 0xffffffff00ffffffff)")
== B_OK);
CHK(type.SetTo(testType1) == B_OK);
CHK(type.Install() == B_OK);
CHK(type.SetSnifferRule("0.4 ('ABCD')") == B_OK);
CHK(type.SetTo(testType2) == B_OK);
CHK(type.Install() == B_OK);
#if TEST_R5
CHK(type.SetSnifferRule("0.4 [0] ('XYZ') | [0:5] ('CD E')") == B_OK);
#else
#endif
CHK(type.SetTo(testType3) == B_OK);
CHK(type.Install() == B_OK);
CHK(type.SetSnifferRule("0.3 [0:8] ('ABCD' | 'EFGH')") == B_OK);
CHK(type.SetTo(testType4) == B_OK);
CHK(type.Install() == B_OK);
CHK(type.SetSnifferRule("0.2 [0:3] ('ABCD' | 'abcd')") == B_OK);
CHK(type.SetTo(testType5) == B_OK);
CHK(type.Install() == B_OK);
CHK(type.SetSnifferRule("0.2 ('LMNO' & 0xfffeffff)") == B_OK);
}
SniffingTestFile files[] = {
SniffingTestFile(string(testDir) + "/file1.cpp",
"text/x-source-code", ""),
SniffingTestFile(string(testDir) + "/file2.gif",
"image/gif", ""),
SniffingTestFile(string(testDir) + "/file3",
"", "text/html",
"<html>\n<body>\n</body></html>\n"),
SniffingTestFile(string(testDir) + "/file4.cpp",
"text/x-source-code", "text/html",
"<html>\n<body>\n</body></html>\n"),
SniffingTestFile(string(testDir) + "/file5", "", testType1, "ABCD"),
SniffingTestFile(string(testDir) + "/file6", "", testType3, " ABCD"),
SniffingTestFile(string(testDir) + "/file7", "", testType4, "abcd"),
SniffingTestFile(string(testDir) + "/file8", "", testType3,
" ABCDEFGH"),
SniffingTestFile(string(testDir) + "/file9", "", testType,
" ABCD EFGH"),
SniffingTestFile(string(testDir) + "/file10", "", testType3,
" ABCD EFGH"),
SniffingTestFile(string(testDir) + "/file11", "", testType5,
"LMNO"),
SniffingTestFile(string(testDir) + "/file12", "", testType5,
"LLNO"),
SniffingTestFile(string(testDir) + "/file13", "", "",
"LNNO"),
};
int fileCount = sizeof(files) / sizeof(SniffingTestFile);
for (int32 i = 0; i < fileCount; i++) {
NextSubTest();
SniffingTestFile &file = files[i];
const char *filename = file.name.c_str();
const char *extensionType = file.extensionType.c_str();
const char *contentType = file.contentType.c_str();
const char *realType = contentType;
if (file.contentType == "application/octet-stream")
realType = extensionType;
BMimeType type;
CHK(BMimeType::GuessMimeType(filename, &type) == B_OK);
CHK(type == extensionType);
type.Unset();
if (file.data != NULL) {
CHK(BMimeType::GuessMimeType(file.data, file.size, &type) == B_OK);
if (!(type == contentType))
printf("type: %s, should be: %s\n", type.Type(), realType);
CHK(type == contentType);
type.Unset();
}
CHK(file.Create() == B_OK);
BNode node;
CHK(node.SetTo(filename) == B_OK);
CHK(WriteStringAttr(node, "BEOS:TYPE", "application/x-person") == B_OK);
entry_ref ref;
CHK(get_ref_for_path(filename, &ref) == B_OK);
CHK(BMimeType::GuessMimeType(&ref, &type) == B_OK);
if (!(type == realType))
printf("type: %s, should be: %s (file == '%s')\n", type.Type(), realType, filename);
CHK(type == realType);
type.Unset();
CHK(file.Delete() == B_OK);
}
{
NextSubTest();
string filename = string(testDir) + "/file100.cpp";
BMimeType type;
entry_ref ref;
#if TEST_R5
CHK(BMimeType::GuessMimeType(&ref, &type) == B_OK);
CHK(type == "application/octet-stream");
#else
CHK(BMimeType::GuessMimeType(&ref, &type) != B_OK);
#endif
CHK(get_ref_for_path(filename.c_str(), &ref) == B_OK);
CHK(BMimeType::GuessMimeType(&ref, &type) != B_OK);
}
{
NextSubTest();
SniffingTestFile &file = files[0];
CHK(file.Create() == B_OK);
const char *filename = file.name.c_str();
entry_ref ref;
CHK(get_ref_for_path(filename, &ref) == B_OK);
BMimeType type;
CHK(BMimeType::GuessMimeType(filename, NULL) == B_BAD_VALUE);
CHK(BMimeType::GuessMimeType(file.data, file.size, NULL)
== B_BAD_VALUE);
CHK(BMimeType::GuessMimeType(&ref, NULL) == B_BAD_VALUE);
CHK(BMimeType::GuessMimeType((const char*)NULL, &type) == B_BAD_VALUE);
CHK(BMimeType::GuessMimeType(NULL, 10, &type) == B_BAD_VALUE);
CHK(BMimeType::GuessMimeType((const entry_ref*)NULL, &type)
== B_BAD_VALUE);
CHK(BMimeType::GuessMimeType((const char*)NULL, NULL) == B_BAD_VALUE);
CHK(BMimeType::GuessMimeType(NULL, 10, NULL) == B_BAD_VALUE);
CHK(BMimeType::GuessMimeType((const entry_ref*)NULL, NULL)
== B_BAD_VALUE);
CHK(file.Delete() == B_OK);
}
}