Merge topic 'list_sort'

49a51a61d7 list: Add options to control the SORT comparison operation

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2065
diff --git a/Help/command/list.rst b/Help/command/list.rst
index 589e572..ad2c428 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -28,7 +28,7 @@
 
   `Ordering`_
     list(`REVERSE`_ <list>)
-    list(`SORT`_ <list>)
+    list(`SORT`_ <list> [...])
 
 Introduction
 ^^^^^^^^^^^^
@@ -253,7 +253,23 @@
 
 ::
 
-  list(SORT <list>)
-
+  list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
 
 Sorts the list in-place alphabetically.
+Use the option ``<compare>`` to select the compare type for sorting.
+The ``<compare>`` option may be one of:
+
+* ``STRING``: Sorts a list of strings alphabetically.
+* ``FILE_BASENAME``: Sort a list of pathnames of files by their basenames.
+
+Use the option ``<case>`` to select a case sensitive or case insensitive sort mode.
+The ``<case>`` option may be one of:
+
+* ``SENSITIVE``: Sorts the list alphabetically.
+* ``INSENSITIVE``: Sorts the list alphabetically in descending order.
+
+Use the option ``<order>`` to select a case sensitive or case insensitive sort mode.
+The ``<order>`` option may be one of:
+
+* ``ASCENDING``: Sorts the list in ascending order.
+* ``DESCENDING``: Sorts the list in descending order.
diff --git a/Help/release/dev/list_sort.rst b/Help/release/dev/list_sort.rst
new file mode 100644
index 0000000..8971b78
--- /dev/null
+++ b/Help/release/dev/list_sort.rst
@@ -0,0 +1,5 @@
+list_sort
+---------
+
+* The :command:`list(SORT)` command gained options to control the
+  comparison operation used to order the entries.
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 1ac2cc2..ba0c843 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -963,14 +963,193 @@
   return true;
 }
 
+class cmStringSorter
+{
+public:
+  enum class Order
+  {
+    UNINITIALIZED,
+    ASCENDING,
+    DESCENDING,
+  };
+
+  enum class Compare
+  {
+    UNINITIALIZED,
+    STRING,
+    FILE_BASENAME,
+  };
+  enum class CaseSensitivity
+  {
+    UNINITIALIZED,
+    SENSITIVE,
+    INSENSITIVE,
+  };
+
+protected:
+  typedef std::string (*StringFilter)(const std::string& in);
+  StringFilter GetCompareFilter(Compare compare)
+  {
+    return (compare == Compare::FILE_BASENAME) ? cmSystemTools::GetFilenameName
+                                               : nullptr;
+  }
+
+  StringFilter GetCaseFilter(CaseSensitivity sensitivity)
+  {
+    return (sensitivity == CaseSensitivity::INSENSITIVE)
+      ? cmSystemTools::LowerCase
+      : nullptr;
+  }
+
+public:
+  cmStringSorter(Compare compare, CaseSensitivity caseSensitivity,
+                 Order desc = Order::ASCENDING)
+    : filters{ GetCompareFilter(compare), GetCaseFilter(caseSensitivity) }
+    , descending(desc == Order::DESCENDING)
+  {
+  }
+
+  std::string ApplyFilter(const std::string& argument)
+  {
+    std::string result = argument;
+    for (auto filter : filters) {
+      if (filter != nullptr) {
+        result = filter(result);
+      }
+    }
+    return result;
+  }
+
+  bool operator()(const std::string& a, const std::string& b)
+  {
+    std::string af = ApplyFilter(a);
+    std::string bf = ApplyFilter(b);
+    bool result;
+    if (descending) {
+      result = bf < af;
+    } else {
+      result = af < bf;
+    }
+    return result;
+  }
+
+protected:
+  StringFilter filters[2] = { nullptr, nullptr };
+  bool descending;
+};
+
 bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
 {
   assert(args.size() >= 2);
-  if (args.size() > 2) {
-    this->SetError("sub-command SORT only takes one argument.");
+  if (args.size() > 8) {
+    this->SetError("sub-command SORT only takes up to six arguments.");
     return false;
   }
 
+  auto sortCompare = cmStringSorter::Compare::UNINITIALIZED;
+  auto sortCaseSensitivity = cmStringSorter::CaseSensitivity::UNINITIALIZED;
+  auto sortOrder = cmStringSorter::Order::UNINITIALIZED;
+
+  size_t argumentIndex = 2;
+  const std::string messageHint = "sub-command SORT ";
+
+  while (argumentIndex < args.size()) {
+    const std::string option = args[argumentIndex++];
+    if (option == "COMPARE") {
+      if (sortCompare != cmStringSorter::Compare::UNINITIALIZED) {
+        std::string error = messageHint + "option \"" + option +
+          "\" has been specified multiple times.";
+        this->SetError(error);
+        return false;
+      }
+      if (argumentIndex < args.size()) {
+        const std::string argument = args[argumentIndex++];
+        if (argument == "STRING") {
+          sortCompare = cmStringSorter::Compare::STRING;
+        } else if (argument == "FILE_BASENAME") {
+          sortCompare = cmStringSorter::Compare::FILE_BASENAME;
+        } else {
+          std::string error = messageHint + "value \"" + argument +
+            "\" for option \"" + option + "\" is invalid.";
+          this->SetError(error);
+          return false;
+        }
+      } else {
+        std::string error =
+          messageHint + "missing argument for option \"" + option + "\".";
+        this->SetError(error);
+        return false;
+      }
+    } else if (option == "CASE") {
+      if (sortCaseSensitivity !=
+          cmStringSorter::CaseSensitivity::UNINITIALIZED) {
+        std::string error = messageHint + "option \"" + option +
+          "\" has been specified multiple times.";
+        this->SetError(error);
+        return false;
+      }
+      if (argumentIndex < args.size()) {
+        const std::string argument = args[argumentIndex++];
+        if (argument == "SENSITIVE") {
+          sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
+        } else if (argument == "INSENSITIVE") {
+          sortCaseSensitivity = cmStringSorter::CaseSensitivity::INSENSITIVE;
+        } else {
+          std::string error = messageHint + "value \"" + argument +
+            "\" for option \"" + option + "\" is invalid.";
+          this->SetError(error);
+          return false;
+        }
+      } else {
+        std::string error =
+          messageHint + "missing argument for option \"" + option + "\".";
+        this->SetError(error);
+        return false;
+      }
+    } else if (option == "ORDER") {
+
+      if (sortOrder != cmStringSorter::Order::UNINITIALIZED) {
+        std::string error = messageHint + "option \"" + option +
+          "\" has been specified multiple times.";
+        this->SetError(error);
+        return false;
+      }
+      if (argumentIndex < args.size()) {
+        const std::string argument = args[argumentIndex++];
+        if (argument == "ASCENDING") {
+          sortOrder = cmStringSorter::Order::ASCENDING;
+        } else if (argument == "DESCENDING") {
+          sortOrder = cmStringSorter::Order::DESCENDING;
+        } else {
+          std::string error = messageHint + "value \"" + argument +
+            "\" for option \"" + option + "\" is invalid.";
+          this->SetError(error);
+          return false;
+        }
+      } else {
+        std::string error =
+          messageHint + "missing argument for option \"" + option + "\".";
+        this->SetError(error);
+        return false;
+      }
+    } else {
+      std::string error =
+        messageHint + "option \"" + option + "\" is unknown.";
+      this->SetError(error);
+      return false;
+    }
+  }
+  // set Default Values if Option is not given
+  if (sortCompare == cmStringSorter::Compare::UNINITIALIZED) {
+    sortCompare = cmStringSorter::Compare::STRING;
+  }
+  if (sortCaseSensitivity == cmStringSorter::CaseSensitivity::UNINITIALIZED) {
+    sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
+  }
+  if (sortOrder == cmStringSorter::Order::UNINITIALIZED) {
+    sortOrder = cmStringSorter::Order::ASCENDING;
+  }
+
   const std::string& listName = args[1];
   // expand the variable
   std::vector<std::string> varArgsExpanded;
@@ -979,7 +1158,14 @@
     return false;
   }
 
-  std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
+  if ((sortCompare == cmStringSorter::Compare::STRING) &&
+      (sortCaseSensitivity == cmStringSorter::CaseSensitivity::SENSITIVE) &&
+      (sortOrder == cmStringSorter::Order::ASCENDING)) {
+    std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
+  } else {
+    cmStringSorter sorter(sortCompare, sortCaseSensitivity, sortOrder);
+    std::sort(varArgsExpanded.begin(), varArgsExpanded.end(), sorter);
+  }
 
   std::string value = cmJoin(varArgsExpanded, ";");
   this->Makefile->AddDefinition(listName, value.c_str());
diff --git a/Tests/RunCMake/list/RunCMakeTest.cmake b/Tests/RunCMake/list/RunCMakeTest.cmake
index bdc23a4..a8a0b57 100644
--- a/Tests/RunCMake/list/RunCMakeTest.cmake
+++ b/Tests/RunCMake/list/RunCMakeTest.cmake
@@ -20,7 +20,6 @@
 run_cmake(LENGTH-TooManyArguments)
 run_cmake(REMOVE_DUPLICATES-TooManyArguments)
 run_cmake(REVERSE-TooManyArguments)
-run_cmake(SORT-TooManyArguments)
 run_cmake(SUBLIST-TooManyArguments)
 
 run_cmake(FILTER-NotList)
@@ -84,3 +83,16 @@
 run_cmake(TRANSFORM-APPEND)
 run_cmake(TRANSFORM-PREPEND)
 run_cmake(TRANSFORM-REPLACE)
+
+# argument tests
+run_cmake(SORT-WrongOption)
+run_cmake(SORT-BadCaseOption)
+run_cmake(SORT-BadCompareOption)
+run_cmake(SORT-BadOrderOption)
+run_cmake(SORT-DuplicateOrderOption)
+run_cmake(SORT-DuplicateCompareOption)
+run_cmake(SORT-DuplicateCaseOption)
+run_cmake(SORT-NoCaseOption)
+
+# Successful tests
+run_cmake(SORT)
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-BadCaseOption-result.txt
similarity index 100%
rename from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
rename to Tests/RunCMake/list/SORT-BadCaseOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-BadCaseOption-stderr.txt b/Tests/RunCMake/list/SORT-BadCaseOption-stderr.txt
new file mode 100644
index 0000000..87dd502
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-BadCaseOption-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at SORT-BadCaseOption.cmake:1 \(list\):
+  list sub-command SORT value "BAD_CASE_OPTION" for option "CASE" is invalid.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-BadCaseOption.cmake b/Tests/RunCMake/list/SORT-BadCaseOption.cmake
new file mode 100644
index 0000000..ac5c102
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-BadCaseOption.cmake
@@ -0,0 +1 @@
+list(SORT mylist CASE BAD_CASE_OPTION)
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-BadCompareOption-result.txt
similarity index 100%
copy from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
copy to Tests/RunCMake/list/SORT-BadCompareOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-BadCompareOption-stderr.txt b/Tests/RunCMake/list/SORT-BadCompareOption-stderr.txt
new file mode 100644
index 0000000..51b4de2
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-BadCompareOption-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at SORT-BadCompareOption.cmake:1 \(list\):
+  list sub-command SORT value "BAD_COMPARE_OPTION" for option "COMPARE" is
+  invalid.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-BadCompareOption.cmake b/Tests/RunCMake/list/SORT-BadCompareOption.cmake
new file mode 100644
index 0000000..d5c632e
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-BadCompareOption.cmake
@@ -0,0 +1 @@
+list(SORT mylist COMPARE BAD_COMPARE_OPTION)
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-BadOrderOption-result.txt
similarity index 100%
copy from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
copy to Tests/RunCMake/list/SORT-BadOrderOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-BadOrderOption-stderr.txt b/Tests/RunCMake/list/SORT-BadOrderOption-stderr.txt
new file mode 100644
index 0000000..7984e5c
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-BadOrderOption-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at SORT-BadOrderOption.cmake:1 \(list\):
+  list sub-command SORT value "BAD_ODER_OPTION" for option "ORDER" is
+  invalid.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-BadOrderOption.cmake b/Tests/RunCMake/list/SORT-BadOrderOption.cmake
new file mode 100644
index 0000000..e232197
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-BadOrderOption.cmake
@@ -0,0 +1 @@
+list(SORT mylist ORDER BAD_ODER_OPTION)
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-DuplicateCaseOption-result.txt
similarity index 100%
copy from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
copy to Tests/RunCMake/list/SORT-DuplicateCaseOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-DuplicateCaseOption-stderr.txt b/Tests/RunCMake/list/SORT-DuplicateCaseOption-stderr.txt
new file mode 100644
index 0000000..b893f50
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-DuplicateCaseOption-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at SORT-DuplicateCaseOption.cmake:2 \(list\):
+  list sub-command SORT option "CASE" has been specified multiple times.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-DuplicateCaseOption.cmake b/Tests/RunCMake/list/SORT-DuplicateCaseOption.cmake
new file mode 100644
index 0000000..ba52b24
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-DuplicateCaseOption.cmake
@@ -0,0 +1,2 @@
+set (mylist a b c)
+list(SORT mylist CASE INSENSITIVE CASE INSENSITIVE )
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-DuplicateCompareOption-result.txt
similarity index 100%
copy from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
copy to Tests/RunCMake/list/SORT-DuplicateCompareOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-DuplicateCompareOption-stderr.txt b/Tests/RunCMake/list/SORT-DuplicateCompareOption-stderr.txt
new file mode 100644
index 0000000..83624be
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-DuplicateCompareOption-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at SORT-DuplicateCompareOption.cmake:2 \(list\):
+  list sub-command SORT option "COMPARE" has been specified multiple times.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-DuplicateCompareOption.cmake b/Tests/RunCMake/list/SORT-DuplicateCompareOption.cmake
new file mode 100644
index 0000000..fd2e31d
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-DuplicateCompareOption.cmake
@@ -0,0 +1,2 @@
+set (mylist a b c)
+list(SORT mylist COMPARE STRING COMPARE STRING)
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-DuplicateOrderOption-result.txt
similarity index 100%
copy from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
copy to Tests/RunCMake/list/SORT-DuplicateOrderOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-DuplicateOrderOption-stderr.txt b/Tests/RunCMake/list/SORT-DuplicateOrderOption-stderr.txt
new file mode 100644
index 0000000..9e95178
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-DuplicateOrderOption-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at SORT-DuplicateOrderOption.cmake:2 \(list\):
+  list sub-command SORT option "ORDER" has been specified multiple times.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-DuplicateOrderOption.cmake b/Tests/RunCMake/list/SORT-DuplicateOrderOption.cmake
new file mode 100644
index 0000000..26d9c7d
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-DuplicateOrderOption.cmake
@@ -0,0 +1,2 @@
+set (mylist a b c)
+list(SORT mylist ORDER ASCENDING ORDER ASCENDING)
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-NoCaseOption-result.txt
similarity index 100%
copy from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
copy to Tests/RunCMake/list/SORT-NoCaseOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-NoCaseOption-stderr.txt b/Tests/RunCMake/list/SORT-NoCaseOption-stderr.txt
new file mode 100644
index 0000000..5c63e77
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-NoCaseOption-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at SORT-NoCaseOption.cmake:1 \(list\):
+  list sub-command SORT missing argument for option "CASE".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-NoCaseOption.cmake b/Tests/RunCMake/list/SORT-NoCaseOption.cmake
new file mode 100644
index 0000000..57cc429
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-NoCaseOption.cmake
@@ -0,0 +1 @@
+list(SORT mylist CASE)
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-stderr.txt b/Tests/RunCMake/list/SORT-TooManyArguments-stderr.txt
deleted file mode 100644
index d3fad60..0000000
--- a/Tests/RunCMake/list/SORT-TooManyArguments-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-^CMake Error at SORT-TooManyArguments.cmake:1 \(list\):
-  list sub-command SORT only takes one argument.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments-result.txt b/Tests/RunCMake/list/SORT-WrongOption-result.txt
similarity index 100%
copy from Tests/RunCMake/list/SORT-TooManyArguments-result.txt
copy to Tests/RunCMake/list/SORT-WrongOption-result.txt
diff --git a/Tests/RunCMake/list/SORT-WrongOption-stderr.txt b/Tests/RunCMake/list/SORT-WrongOption-stderr.txt
new file mode 100644
index 0000000..597cb29
--- /dev/null
+++ b/Tests/RunCMake/list/SORT-WrongOption-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at SORT-WrongOption.cmake:1 \(list\):
+  list sub-command SORT option "one_too_many" is unknown.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/SORT-TooManyArguments.cmake b/Tests/RunCMake/list/SORT-WrongOption.cmake
similarity index 100%
rename from Tests/RunCMake/list/SORT-TooManyArguments.cmake
rename to Tests/RunCMake/list/SORT-WrongOption.cmake
diff --git a/Tests/RunCMake/list/SORT.cmake b/Tests/RunCMake/list/SORT.cmake
new file mode 100644
index 0000000..4a9e064
--- /dev/null
+++ b/Tests/RunCMake/list/SORT.cmake
@@ -0,0 +1,114 @@
+set(source_unsorted
+        c/B.h
+        a/c.h
+        B/a.h
+        )
+
+## Test with default options
+set(expected
+        B/a.h
+        a/c.h
+        c/B.h
+        )
+set(list ${source_unsorted})
+list(SORT list)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE STRING)")
+endif ()
+
+
+## Test CASE INSENSITIVE ORDER ASCENDING COMPARE STRING
+set(expected
+        a/c.h
+        B/a.h
+        c/B.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE INSENSITIVE ORDER DESCENDING COMPARE STRING
+set(expected
+        c/B.h
+        B/a.h
+        a/c.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE SENSITIVE ORDER ASCENDING COMPARE STRING
+set(expected
+        B/a.h
+        a/c.h
+        c/B.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE SENSITIVE ORDER DESCENDING COMPARE STRING
+set(expected
+        c/B.h
+        a/c.h
+        B/a.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE INSENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME
+set(expected
+        B/a.h
+        c/B.h
+        a/c.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)")
+endif ()
+
+## Test CASE INSENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME
+set(expected
+        a/c.h
+        c/B.h
+        B/a.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)")
+endif ()
+
+## Test CASE SENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME
+set(expected
+        c/B.h
+        B/a.h
+        a/c.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)")
+endif ()
+
+## Test CASE SENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME
+set(expected
+        a/c.h
+        B/a.h
+        c/B.h
+        )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+    message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)")
+endif ()