1#!/usr/bin/env escript
2%% -*- erlang -*-
3%%! -smp enable
4
5% Licensed under the Apache License, Version 2.0 (the "License"); you may not
6% use this file except in compliance with the License. You may obtain a copy of
7% the License at
8%
9%   http://www.apache.org/licenses/LICENSE-2.0
10%
11% Unless required by applicable law or agreed to in writing, software
12% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14% License for the specific language governing permissions and limitations under
15% the License.
16
17default_config() ->
18    test_util:build_file("etc/couchdb/default_dev.ini").
19
20local_config_1() ->
21    test_util:source_file("test/etap/081-config-override.1.ini").
22
23local_config_2() ->
24    test_util:source_file("test/etap/081-config-override.2.ini").
25
26local_config_write() ->
27    test_util:build_file("test/etap/temp.081").
28
29% Run tests and wait for the config gen_server to shutdown.
30run_tests(IniFiles, Tests) ->
31    {ok, Pid} = couch_config:start_link(IniFiles),
32    erlang:monitor(process, Pid),
33    Tests(),
34    couch_config:stop(),
35    receive
36        {'DOWN', _, _, Pid, _} -> ok;
37        _Other -> etap:diag("OTHER: ~p~n", [_Other])
38    after
39        1000 -> throw({timeout_error, config_stop})
40    end.
41
42main(_) ->
43    test_util:init_code_path(),
44    etap:plan(15),
45
46    case (catch test()) of
47        ok ->
48            etap:end_tests();
49        Other ->
50            etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
51            etap:bail(Other)
52    end,
53    ok.
54
55test() ->
56
57    CheckStartStop = fun() -> ok end,
58    run_tests([default_config()], CheckStartStop),
59
60    CheckDefaults = fun() ->
61        etap:is(
62            couch_config:get("httpd","port"),
63            "5984",
64            "{httpd, port} is 5984 by default"
65        ),
66
67        etap:is(
68            couch_config:get("fizbang", "unicode"),
69            undefined,
70            "{fizbang, unicode} is undefined by default"
71        )
72    end,
73
74    run_tests([default_config()], CheckDefaults),
75
76
77    % Check that subsequent files override values appropriately
78
79    CheckOverride = fun() ->
80        etap:is(
81            couch_config:get("httpd", "port"),
82            "4895",
83            "{httpd, port} was overriden with the value 4895"
84        )
85    end,
86
87    run_tests([default_config(), local_config_1()], CheckOverride),
88
89
90    % Check that overrides can create new sections
91
92    CheckOverride2 = fun() ->
93        etap:is(
94            couch_config:get("httpd", "port"),
95            "80",
96            "{httpd, port} is overriden with the value 80"
97        ),
98
99        etap:is(
100            couch_config:get("fizbang", "unicode"),
101            "normalized",
102            "{fizbang, unicode} was created by override INI file"
103        )
104    end,
105
106    run_tests([default_config(), local_config_2()], CheckOverride2),
107
108
109    % Check that values can be overriden multiple times
110
111    CheckOverride3 = fun() ->
112        etap:is(
113            couch_config:get("httpd", "port"),
114            "80",
115            "{httpd, port} value was taken from the last specified INI file."
116        )
117    end,
118
119    run_tests(
120        [default_config(), local_config_1(), local_config_2()],
121        CheckOverride3
122    ),
123
124    % Check persistence to last file.
125
126    % Empty the file in case it exists.
127    {ok, Fd} = file:open(local_config_write(), write),
128    ok = file:truncate(Fd),
129    ok = file:close(Fd),
130
131    {Field, Addr} = case misc:is_ipv6() of
132                true -> {"ip6_bind_address", "::1"};
133                false -> {"ip4_bind_address", "127.0.0.1"}
134            end,
135
136
137    % Open and write a value
138    CheckCanWrite = fun() ->
139        etap:is(
140            couch_config:get("httpd", "port"),
141            "5984",
142            "{httpd, port} is still 5984 by default"
143        ),
144
145        etap:is(
146            couch_config:set("httpd", "port", "8080"),
147            ok,
148            "Writing {httpd, port} is kosher."
149        ),
150
151        etap:is(
152            couch_config:get("httpd", "port"),
153            "8080",
154            "{httpd, port} was updated to 8080 successfully."
155        ),
156
157        etap:is(
158            couch_config:delete("httpd", Field),
159            ok,
160            "Deleting {httpd, " ++ Field ++ "} succeeds"
161        ),
162
163        etap:is(
164            couch_config:get("httpd", Field),
165            undefined,
166            "{httpd, " ++ Field ++ "} was actually deleted."
167        )
168    end,
169
170    run_tests([default_config(), local_config_write()], CheckCanWrite),
171
172    % Open and check where we don't expect persistence.
173
174    CheckDidntWrite = fun() ->
175        etap:is(
176            couch_config:get("httpd", "port"),
177            "5984",
178            "{httpd, port} was not persisted to the primary INI file."
179        ),
180
181        etap:is(
182            couch_config:get("httpd", Field),
183            Addr,
184            "{httpd, " ++ Field ++ "} was not deleted form the primary INI file."
185        )
186    end,
187
188    run_tests([default_config()], CheckDidntWrite),
189
190    % Open and check we have only the persistence we expect.
191    CheckDidWrite = fun() ->
192        etap:is(
193            couch_config:get("httpd", "port"),
194            "8080",
195            "{httpd, port} is still 8080 after reopening the config."
196        ),
197
198        etap:is(
199            couch_config:get("httpd", Field),
200            undefined,
201            "{httpd, " ++ Field ++ "} is still \"\" after reopening."
202        )
203    end,
204
205    run_tests([local_config_write()], CheckDidWrite),
206
207    ok.
208