From dcae06a5c5833460767caca27cd3962974a94abb Mon Sep 17 00:00:00 2001
From: Tobias Hunger <tobias.hunger@nokia.com>
Date: Mon, 21 Mar 2011 18:04:24 +0100
Subject: [PATCH] Unit test for Abi::abisOfBinary(...)

---
 src/plugins/projectexplorer/abi.cpp           | 124 ++++++++++++++++--
 src/plugins/projectexplorer/projectexplorer.h |   3 +
 2 files changed, 119 insertions(+), 8 deletions(-)

diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index 8e363d69234..dc4dfda6813 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -141,6 +141,9 @@ static QList<Abi> abiOf(const QByteArray &data)
         case 21: // EM_PPC64
             result.append(Abi(Abi::PowerPCArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 64));
             break;
+        case 40: // EM_ARM
+            result.append(Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32));
+            break;
         case 62: // EM_X86_64
             result.append(Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 64));
             break;
@@ -171,6 +174,10 @@ static QList<Abi> abiOf(const QByteArray &data)
             result.append(macAbiForCpu(type));
             pos += 20;
         }
+    } else if (data.size() >= 20
+               && static_cast<unsigned char>(data.at(16)) == 'E' && static_cast<unsigned char>(data.at(17)) == 'P'
+               && static_cast<unsigned char>(data.at(18)) == 'O' && static_cast<unsigned char>(data.at(19)) == 'C') {
+        result.append(Abi(Abi::ArmArchitecture, Abi::SymbianOS, Abi::SymbianDeviceFlavor, Abi::ElfFormat, 32));
     } else {
         // Windows PE
         // Windows can have its magic bytes everywhere...
@@ -492,13 +499,13 @@ Abi Abi::hostAbi()
 
 QList<Abi> Abi::abisOfBinary(const QString &path)
 {
-    QList<Abi> result;
+    QList<Abi> tmp;
     if (path.isEmpty())
-        return result;
+        return tmp;
 
     QFile f(path);
     if (!f.exists())
-        return result;
+        return tmp;
 
     bool windowsStatic = path.endsWith(QLatin1String(".lib"));
 
@@ -509,7 +516,7 @@ QList<Abi> Abi::abisOfBinary(const QString &path)
             && static_cast<unsigned char>(data.at(2)) == 'a' && static_cast<unsigned char>(data.at(3)) == 'r'
             && static_cast<unsigned char>(data.at(4)) == 'c' && static_cast<unsigned char>(data.at(5)) == 'h'
             && static_cast<unsigned char>(data.at(6)) == '>' && static_cast<unsigned char>(data.at(7)) == 0x0a) {
-        // We got an ar file: possibly a static lib for ELF or Mach-O
+        // We got an ar file: possibly a static lib for ELF, PE or Mach-O
 
         data = data.mid(8); // Cut of ar file magic
         quint64 offset = 8;
@@ -530,22 +537,123 @@ QList<Abi> Abi::abisOfBinary(const QString &path)
             offset += fileLength.toInt() + 60 /* header */;
             if (windowsStatic) {
                 if (fileName == QLatin1String("/0              "))
-                    result = parseCoffHeader(data.mid(toSkip, 20));
+                    tmp = parseCoffHeader(data.mid(toSkip, 20));
             } else {
-                result = abiOf(data.mid(toSkip));
+                tmp.append(abiOf(data.mid(toSkip)));
             }
-            if (!result.isEmpty())
+            if (!tmp.isEmpty()
+                    && tmp.at(0).binaryFormat() != Abi::MachOFormat)
                 break;
 
             f.seek(offset + (offset % 2)); // ar is 2 byte alligned
             data = f.read(1024);
         }
     } else {
-        result = abiOf(data);
+        tmp = abiOf(data);
     }
     f.close();
 
+    // Remove duplicates:
+    QList<Abi> result;
+    foreach (const Abi &a, tmp) {
+        if (!result.contains(a))
+            result.append(a);
+    }
+
     return result;
 }
 
 } // namespace ProjectExplorer
+
+// Unit tests:
+#ifdef WITH_TESTS
+#   include <QTest>
+#   include <QtCore/QFileInfo>
+
+#   include "projectexplorer.h"
+
+void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary_data()
+{
+    QTest::addColumn<QString>("file");
+    QTest::addColumn<QStringList>("abis");
+
+    QTest::newRow("no file")
+            << QString()
+            << (QStringList());
+    QTest::newRow("non existing file")
+            << QString::fromLatin1("/does/not/exist")
+            << (QStringList());
+
+    // Set up prefix for test data now that we can be sure to have some tests to run:
+    QString prefix = qgetenv("QTC_TEST_EXTRADATALOCATION");
+    if (prefix.isEmpty())
+        return;
+    QFileInfo fi(prefix);
+    if (!fi.exists() || !fi.isDir())
+        return;
+    prefix = fi.absoluteFilePath();
+
+    QTest::newRow("text file")
+            << QString::fromLatin1("%1/broken/text.txt").arg(prefix)
+            << (QStringList());
+
+    QTest::newRow("static QtCore: win msvc2008")
+            << QString::fromLatin1("%1/abi/static/win_msvc2008_release.lib").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-windows-unknown-pe-32bit"));
+    QTest::newRow("static QtCore: win msvc2008 (debug)")
+            << QString::fromLatin1("%1/abi/static/win_msvc2008_debug.lib").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-windows-unknown-pe-32bit"));
+    QTest::newRow("static QtCore: mac (debug)")
+            << QString::fromLatin1("%1/abi/static/mac-32bit-debug.a").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-macos-generic-mach_o-32bit"));
+    QTest::newRow("static QtCore: linux 32bit")
+            << QString::fromLatin1("%1/abi/static/linux-32bit-release.a").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-linux-generic-elf-32bit"));
+    QTest::newRow("static QtCore: linux 64bit")
+            << QString::fromLatin1("%1/abi/static/linux-64bit-release.a").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-linux-generic-elf-64bit"));
+
+    QTest::newRow("static stdc++: mac fat")
+            << QString::fromLatin1("%1/abi/static/mac-fat.a").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-macos-generic-mach_o-32bit")
+                              << QString::fromLatin1("ppc-macos-generic-mach_o-32bit")
+                              << QString::fromLatin1("x86-macos-generic-mach_o-64bit"));
+
+    QTest::newRow("dynamic QtCore: symbian")
+            << QString::fromLatin1("%1/abi/dynamic/symbian.dll").arg(prefix)
+            << (QStringList() << QString::fromLatin1("arm-symbian-device-elf-32bit"));
+    QTest::newRow("dynamic QtCore: win msvc2010 64bit")
+            << QString::fromLatin1("%1/abi/dynamic/win-msvc2010-64bit.dll").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-windows-msvc2010-pe-64bit"));
+    QTest::newRow("dynamic QtCore: win msvc2008 32bit")
+            << QString::fromLatin1("%1/abi/dynamic/win-msvc2008-32bit.dll").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-windows-msvc2008-pe-32bit"));
+    QTest::newRow("dynamic QtCore: win msvc2005 32bit")
+            << QString::fromLatin1("%1/abi/dynamic/win-msvc2005-32bit.dll").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-windows-msvc2005-pe-32bit"));
+    QTest::newRow("dynamic QtCore: win msys 32bit")
+            << QString::fromLatin1("%1/abi/dynamic/win-mingw-32bit.dll").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-windows-msys-pe-32bit"));
+    QTest::newRow("dynamic QtCore: win msys 32bit")
+            << QString::fromLatin1("%1/abi/dynamic/win-mingw-32bit.dll").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-windows-msys-pe-32bit"));
+    QTest::newRow("static stdc++: mac fat")
+            << QString::fromLatin1("%1/abi/dynamic/mac-fat.dylib").arg(prefix)
+            << (QStringList() << QString::fromLatin1("x86-macos-generic-mach_o-32bit")
+                              << QString::fromLatin1("ppc-macos-generic-mach_o-32bit")
+                              << QString::fromLatin1("x86-macos-generic-mach_o-64bit"));
+
+}
+
+void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary()
+{
+    QFETCH(QString, file);
+    QFETCH(QStringList, abis);
+
+    QList<ProjectExplorer::Abi> result = Abi::abisOfBinary(file);
+    QCOMPARE(result.count(), abis.count());
+    for (int i = 0; i < abis.count(); ++i)
+        QCOMPARE(result.at(i).toString(), abis.at(i));
+}
+
+#endif
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index f7c66b53a54..8b8ca79402e 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -236,6 +236,9 @@ private slots:
 
     void testGccAbiGuessing_data();
     void testGccAbiGuessing();
+
+    void testAbiOfBinary_data();
+    void testAbiOfBinary();
 #endif
 
 private:
-- 
GitLab