Add ability to return a "features" list in the welcome message.

This could help users quickly discover the presence of an API or mode of
operation.

Features are obtained from a new config API `config:features/0`

System components can enable features via `config:enable_feature/1` API, or
users can directly enable features in the .ini files, and those features
should show up in the "Welcome" message.

COUCHDB-3180
diff --git a/src/chttpd_misc.erl b/src/chttpd_misc.erl
index 03c665e..cfeeb3f 100644
--- a/src/chttpd_misc.erl
+++ b/src/chttpd_misc.erl
@@ -45,7 +45,8 @@
 handle_welcome_req(#httpd{method='GET'}=Req, WelcomeMessage) ->
     send_json(Req, {[
         {couchdb, WelcomeMessage},
-        {version, list_to_binary(couch_server:get_version())}
+        {version, list_to_binary(couch_server:get_version())},
+        {features, config:features()}
         ] ++ case config:get("vendor") of
         [] ->
             [];
diff --git a/test/chttpd_welcome_test.erl b/test/chttpd_welcome_test.erl
new file mode 100644
index 0000000..55713ec
--- /dev/null
+++ b/test/chttpd_welcome_test.erl
@@ -0,0 +1,83 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_welcome_test).
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+
+-define(USER, "chttpd_db_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(CONTENT_JSON, {"Content-Type", "application/json"}).
+
+
+setup() ->
+    ok = config:set("admins", ?USER, ?PASS, _Persist=false),
+    Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
+    Port = mochiweb_socket_server:get(chttpd, port),
+    Url = lists:concat(["http://", Addr, ":", Port, "/"]),
+    Url.
+
+
+teardown(_Url) ->
+    ok = config:delete("admins", ?USER, _Persist=false).
+
+
+welcome_test_() ->
+    {
+        "chttpd welcome endpoint tests",
+        {
+            setup,
+            fun chttpd_test_util:start_couch/0, fun chttpd_test_util:stop_couch/1,
+            {
+                foreach,
+                fun setup/0, fun teardown/1,
+                [
+                    fun should_have_version/1,
+                    fun should_have_features/1
+                ]
+            }
+        }
+    }.
+
+
+should_have_version(Url) ->
+    ?_test(begin
+        {ok, Status, _, Body} = test_request:get(Url, [?CONTENT_JSON, ?AUTH]),
+        ?assertEqual(200, Status),
+        {Json} = ?JSON_DECODE(Body),
+        Version = couch_util:get_value(<<"version">>, Json, undefined),
+        CouchDB = couch_util:get_value(<<"couchdb">>, Json, undefined),
+        Features = couch_util:get_value(<<"features">>, Json, undefined),
+        ?assertEqual(<<"Welcome">>, CouchDB),
+        RealVersion = list_to_binary(couch_server:get_version()),
+        ?assertEqual(RealVersion, Version),
+        ?assert(is_list(Features))
+    end).
+
+
+should_have_features(Url) ->
+    ?_test(begin
+        config:enable_feature(snek),
+        {ok, 200, _, Body1} = test_request:get(Url, [?CONTENT_JSON, ?AUTH]),
+        {Json1} = ?JSON_DECODE(Body1),
+        Features1 = couch_util:get_value(<<"features">>, Json1, undefined),
+        ?assert(is_list(Features1)),
+        ?assert(lists:member(<<"snek">>, Features1)),
+        config:disable_feature(snek),
+        {ok, 200, _, Body2} = test_request:get(Url, [?CONTENT_JSON, ?AUTH]),
+        {Json2} = ?JSON_DECODE(Body2),
+        Features2 = couch_util:get_value(<<"features">>, Json2, undefined),
+        ?assert(is_list(Features2)),
+        ?assertNot(lists:member(<<"snek">>, Features2))
+    end).