Skip to content

Commit 37eeb1d

Browse files
authored
Merge pull request #1316 from stan-dev/more-information-on-system_error
More information on system error
2 parents f0790df + d52478c commit 37eeb1d

11 files changed

Lines changed: 131 additions & 45 deletions

make/tests

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ test/interface/multi_chain_test$(EXE): $(call depends_on_test_models,
7070
test/interface/optimization_output_test$(EXE): $(call depends_on_test_models, optimization_output simple_jacobian_model)
7171
test/interface/output_sig_figs_test$(EXE): $(call depends_on_test_models, proper_sig_figs)
7272
test/interface/pathfinder_test$(EXE): $(call depends_on_test_models, multi_normal_model eight_schools empty)
73+
test/interface/permissions_test$(EXE): $(call depends_on_test_models, test_model)
7374
test/interface/print_uninitialized_test$(EXE): $(call depends_on_test_models, print_uninitialized)
7475
test/interface/save_metric_json_test$(EXE): $(call depends_on_test_models, simplex_model multi_normal_model)
7576
test/interface/variational_output_test$(EXE): $(call depends_on_test_models, variational_output)

src/cmdstan/file.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ std::ifstream safe_open(const std::string &fname) {
272272
std::unique_ptr<std::ofstream> safe_create(const std::string &fname,
273273
int sig_figs) {
274274
auto ofs = std::make_unique<std::ofstream>(fname.c_str());
275-
ofs->exceptions(std::ofstream::badbit);
275+
ofs->exceptions(std::ofstream::badbit | std::ofstream::failbit);
276276
if (sig_figs > -1) {
277277
ofs->precision(sig_figs);
278278
}

src/cmdstan/main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#include <stdexcept>
2+
#include <iostream>
3+
#include <cerrno>
4+
15
#include <cmdstan/command.hpp>
26
#include <stan/services/error_codes.hpp>
37

@@ -8,6 +12,11 @@ int main(int argc, const char *argv[]) {
812
return cmdstan::return_codes::OK;
913
else
1014
return cmdstan::return_codes::NOT_OK;
15+
} catch (std::system_error &e) {
16+
// system_error is thrown by std::ofstream but the
17+
// message is not always helpful, so we also print errno
18+
std::cerr << e.what() << ": " << std::strerror(errno) << std::endl;
19+
return cmdstan::return_codes::NOT_OK;
1120
} catch (const std::exception &e) {
1221
std::cerr << e.what() << std::endl;
1322
return cmdstan::return_codes::NOT_OK;

src/test/interface/generated_quantities_test.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class CmdStan : public testing::Test {
2929
bern_fitted_params_thin
3030
= {"src", "test", "test-models", "bern_fitted_params_thin.csv"};
3131
default_file_path = {"src", "test", "test-models", "output.csv"};
32-
dev_null_path = {"/dev", "null"};
32+
dummy_output = {"test", "ignored.csv"};
3333
gq_non_scalar_model = {"src", "test", "test-models", "gq_non_scalar"};
3434
gq_non_scalar_fitted_params
3535
= {"src", "test", "test-models", "gq_non_scalar_fitted_params.csv"};
@@ -45,7 +45,7 @@ class CmdStan : public testing::Test {
4545
std::vector<std::string> bern_variational_params;
4646
std::vector<std::string> bern_fitted_params_thin;
4747
std::vector<std::string> default_file_path;
48-
std::vector<std::string> dev_null_path;
48+
std::vector<std::string> dummy_output;
4949
std::vector<std::string> gq_non_scalar_model;
5050
std::vector<std::string> gq_non_scalar_fitted_params;
5151
std::vector<std::string> test_model;
@@ -55,19 +55,19 @@ TEST_F(CmdStan, generate_quantities_good) {
5555
std::stringstream ss;
5656
ss << convert_model_path(bern_gq_model)
5757
<< " data file=" << convert_model_path(bern_data)
58-
<< " output file=" << convert_model_path(dev_null_path)
58+
<< " output file=" << convert_model_path(dummy_output)
5959
<< " method=generate_quantities fitted_params="
6060
<< convert_model_path(bern_fitted_params);
6161
std::string cmd = ss.str();
6262
run_command_output out = run_command(cmd);
63-
ASSERT_FALSE(out.hasError);
63+
ASSERT_FALSE(out.hasError) << out.output;
6464
}
6565

6666
TEST_F(CmdStan, generate_quantities_good_multi) {
6767
std::stringstream ss;
6868
ss << convert_model_path(bern_gq_model)
6969
<< " data file=" << convert_model_path(bern_data)
70-
<< " output file=" << convert_model_path(dev_null_path)
70+
<< " output file=" << convert_model_path(dummy_output)
7171
<< " method=generate_quantities fitted_params="
7272
<< convert_model_path(bern_fitted_params_multi) << " num_chains=4";
7373
std::string cmd = ss.str();
@@ -79,7 +79,7 @@ TEST_F(CmdStan, generate_quantities_good_multi_comma) {
7979
std::stringstream ss;
8080
ss << convert_model_path(bern_gq_model)
8181
<< " data file=" << convert_model_path(bern_data)
82-
<< " output file=" << convert_model_path(dev_null_path)
82+
<< " output file=" << convert_model_path(dummy_output)
8383
<< " method=generate_quantities fitted_params="
8484
<< convert_model_path(bern_fitted_params) << ","
8585
<< convert_model_path(bern_fitted_params) << " num_chains=2";
@@ -115,7 +115,7 @@ TEST_F(CmdStan, generate_quantities_same_in_out_multi_path_diff) {
115115
TEST_F(CmdStan, generate_quantities_non_scalar_good) {
116116
std::stringstream ss;
117117
ss << convert_model_path(gq_non_scalar_model)
118-
<< " output file=" << convert_model_path(dev_null_path)
118+
<< " output file=" << convert_model_path(dummy_output)
119119
<< " method=generate_quantities fitted_params="
120120
<< convert_model_path(gq_non_scalar_fitted_params);
121121
std::string cmd = ss.str();
@@ -126,7 +126,7 @@ TEST_F(CmdStan, generate_quantities_non_scalar_good) {
126126
TEST_F(CmdStan, generate_quantities_no_data_arg) {
127127
std::stringstream ss;
128128
ss << convert_model_path(bern_gq_model)
129-
<< " output file=" << convert_model_path(dev_null_path)
129+
<< " output file=" << convert_model_path(dummy_output)
130130
<< " method=generate_quantities fitted_params="
131131
<< convert_model_path(bern_fitted_params) << " 2>&1";
132132
std::string cmd = ss.str();
@@ -137,7 +137,7 @@ TEST_F(CmdStan, generate_quantities_no_data_arg) {
137137
TEST_F(CmdStan, generate_quantities_no_fitted_params_arg) {
138138
std::stringstream ss;
139139
ss << convert_model_path(bern_gq_model)
140-
<< " output file=" << convert_model_path(dev_null_path)
140+
<< " output file=" << convert_model_path(dummy_output)
141141
<< " method=generate_quantities 2>&1";
142142
std::string cmd = ss.str();
143143
run_command_output out = run_command(cmd);
@@ -148,7 +148,7 @@ TEST_F(CmdStan, generate_quantities_missing_fitted_params) {
148148
std::stringstream ss;
149149
ss << convert_model_path(bern_extra_model)
150150
<< " data file=" << convert_model_path(bern_data)
151-
<< " output file=" << convert_model_path(dev_null_path)
151+
<< " output file=" << convert_model_path(dummy_output)
152152
<< " method=generate_quantities fitted_params="
153153
<< convert_model_path(bern_fitted_params) << " 2>&1";
154154
std::string cmd = ss.str();
@@ -159,7 +159,7 @@ TEST_F(CmdStan, generate_quantities_missing_fitted_params) {
159159
TEST_F(CmdStan, generate_quantities_wrong_csv) {
160160
std::stringstream ss;
161161
ss << convert_model_path(test_model)
162-
<< " output file=" << convert_model_path(dev_null_path)
162+
<< " output file=" << convert_model_path(dummy_output)
163163
<< " method=generate_quantities fitted_params="
164164
<< convert_model_path(bern_fitted_params) << " 2>&1";
165165
std::string cmd = ss.str();

src/test/interface/laplace_test.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class CmdStan : public testing::Test {
2222
multi_normal_mode_json
2323
= {"src", "test", "test-models", "multi_normal_mode.json"};
2424
default_file_path = {"src", "test", "test-models", "output.csv"};
25-
dev_null_path = {"/dev", "null"};
25+
dummy_output = {"test", "ignored.csv"};
2626
wrong_csv = {"src", "test", "test-models", "bern_fitted_params.csv"};
2727
simple_jacobian_model
2828
= {"src", "test", "test-models", "simple_jacobian_model"};
@@ -36,7 +36,7 @@ class CmdStan : public testing::Test {
3636
= {"src", "test", "test-models", "simplex_mode_bad.csv"};
3737
}
3838
std::vector<std::string> default_file_path;
39-
std::vector<std::string> dev_null_path;
39+
std::vector<std::string> dummy_output;
4040
std::vector<std::string> simple_jacobian_model;
4141
std::vector<std::string> simple_jacobian_mode_json;
4242
std::vector<std::string> multi_normal_model;
@@ -56,14 +56,14 @@ class CmdStan : public testing::Test {
5656
TEST_F(CmdStan, laplace_good) {
5757
std::stringstream ss;
5858
ss << convert_model_path(multi_normal_model)
59-
<< " output file=" << convert_model_path(dev_null_path)
59+
<< " output file=" << convert_model_path(dummy_output)
6060
<< " method=laplace mode=" << convert_model_path(multi_normal_mode_csv);
6161
run_command_output out = run_command(ss.str());
6262
ASSERT_FALSE(out.hasError);
6363

6464
ss.str(std::string());
6565
ss << convert_model_path(multi_normal_model)
66-
<< " output file=" << convert_model_path(dev_null_path)
66+
<< " output file=" << convert_model_path(dummy_output)
6767
<< " method=laplace mode=" << convert_model_path(multi_normal_mode_json);
6868
out = run_command(ss.str());
6969
ASSERT_FALSE(out.hasError);
@@ -72,7 +72,7 @@ TEST_F(CmdStan, laplace_good) {
7272
TEST_F(CmdStan, laplace_no_mode_arg) {
7373
std::stringstream ss;
7474
ss << convert_model_path(multi_normal_model)
75-
<< " output file=" << convert_model_path(dev_null_path)
75+
<< " output file=" << convert_model_path(dummy_output)
7676
<< " method=laplace 2>&1";
7777
std::string cmd = ss.str();
7878
run_command_output out = run_command(cmd);
@@ -82,7 +82,7 @@ TEST_F(CmdStan, laplace_no_mode_arg) {
8282
TEST_F(CmdStan, laplace_wrong_mode_file) {
8383
std::stringstream ss;
8484
ss << convert_model_path(multi_normal_model)
85-
<< " output file=" << convert_model_path(dev_null_path)
85+
<< " output file=" << convert_model_path(dummy_output)
8686
<< " method=laplace mode=" << convert_model_path(wrong_csv);
8787
std::string cmd = ss.str();
8888
run_command_output out = run_command(cmd);
@@ -92,7 +92,7 @@ TEST_F(CmdStan, laplace_wrong_mode_file) {
9292
TEST_F(CmdStan, laplace_missing_mode) {
9393
std::stringstream ss;
9494
ss << convert_model_path(multi_normal_model)
95-
<< " output file=" << convert_model_path(dev_null_path)
95+
<< " output file=" << convert_model_path(dummy_output)
9696
<< " method=laplace mode="
9797
<< " 2>&1";
9898
std::string cmd = ss.str();
@@ -103,7 +103,7 @@ TEST_F(CmdStan, laplace_missing_mode) {
103103
TEST_F(CmdStan, laplace_bad_draws_arg) {
104104
std::stringstream ss;
105105
ss << convert_model_path(multi_normal_model)
106-
<< " output file=" << convert_model_path(dev_null_path)
106+
<< " output file=" << convert_model_path(dummy_output)
107107
<< " method=laplace mode=" << convert_model_path(multi_normal_mode_csv)
108108
<< " draws=0 2>&1";
109109
std::string cmd = ss.str();
@@ -114,7 +114,7 @@ TEST_F(CmdStan, laplace_bad_draws_arg) {
114114
TEST_F(CmdStan, laplace_bad_csv_file) {
115115
std::stringstream ss;
116116
ss << convert_model_path(multi_normal_model)
117-
<< " output file=" << convert_model_path(dev_null_path)
117+
<< " output file=" << convert_model_path(dummy_output)
118118
<< " method=laplace mode="
119119
<< convert_model_path(multi_normal_mode_csv_bad_config)
120120
<< " draws=10 2>&1";
@@ -124,7 +124,7 @@ TEST_F(CmdStan, laplace_bad_csv_file) {
124124

125125
ss.str(std::string());
126126
ss << convert_model_path(multi_normal_model)
127-
<< " output file=" << convert_model_path(dev_null_path)
127+
<< " output file=" << convert_model_path(dummy_output)
128128
<< " method=laplace mode="
129129
<< convert_model_path(multi_normal_mode_csv_bad_names) << " draws=10 2>&1";
130130
cmd = ss.str();
@@ -133,7 +133,7 @@ TEST_F(CmdStan, laplace_bad_csv_file) {
133133

134134
ss.str(std::string());
135135
ss << convert_model_path(multi_normal_model)
136-
<< " output file=" << convert_model_path(dev_null_path)
136+
<< " output file=" << convert_model_path(dummy_output)
137137
<< " method=laplace mode="
138138
<< convert_model_path(multi_normal_mode_csv_bad_values)
139139
<< " draws=10 2>&1";

src/test/interface/log_prob_test.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ class CmdStan : public testing::Test {
3030
"bern_unconstrained_params_short.json"};
3131
bern_constrained_params_short
3232
= {"src", "test", "test-models", "bern_constrained_params_short.json"};
33-
dev_null_path = {"/dev", "null"};
3433
test_output = {"test", "output.csv"};
3534
simplex_model = {"src", "test", "test-models", "simplex_model"};
3635
simplex_constrained_bad_csv
@@ -48,7 +47,6 @@ class CmdStan : public testing::Test {
4847
std::vector<std::string> bern_constrained_params_csv;
4948
std::vector<std::string> bern_unconstrained_params_short;
5049
std::vector<std::string> bern_constrained_params_short;
51-
std::vector<std::string> dev_null_path;
5250
std::vector<std::string> test_output;
5351
std::vector<std::string> simplex_model;
5452
std::vector<std::string> simplex_constrained_csv;
@@ -166,7 +164,7 @@ TEST_F(CmdStan, log_prob_no_params) {
166164
std::stringstream ss;
167165
ss << convert_model_path(bern_log_prob_model)
168166
<< " data file=" << convert_model_path(bern_data)
169-
<< " output file=" << convert_model_path(dev_null_path)
167+
<< " output file=" << convert_model_path(test_output)
170168
<< " method=log_prob";
171169
std::string cmd = ss.str();
172170
run_command_output out = run_command(cmd);
@@ -177,7 +175,7 @@ TEST_F(CmdStan, log_prob_constrained_bad_input) {
177175
std::stringstream ss;
178176
ss << convert_model_path(bern_log_prob_model)
179177
<< " data file=" << convert_model_path(bern_data)
180-
<< " output file=" << convert_model_path(dev_null_path)
178+
<< " output file=" << convert_model_path(test_output)
181179
<< " method=log_prob constrained_params="
182180
<< convert_model_path(bern_constrained_params_short);
183181
std::string cmd = ss.str();
@@ -209,7 +207,7 @@ TEST_F(CmdStan, log_prob_constrained_simplex) {
209207
TEST_F(CmdStan, log_prob_constrained_bad_simplex) {
210208
std::stringstream ss;
211209
ss << convert_model_path(simplex_model)
212-
<< " output file=" << convert_model_path(dev_null_path)
210+
<< " output file=" << convert_model_path(test_output)
213211
<< " method=log_prob constrained_params="
214212
<< convert_model_path(simplex_constrained_bad_csv);
215213
std::string cmd = ss.str();
@@ -221,7 +219,7 @@ TEST_F(CmdStan, log_prob_unconstrained_bad_input) {
221219
std::stringstream ss;
222220
ss << convert_model_path(bern_log_prob_model)
223221
<< " data file=" << convert_model_path(bern_data)
224-
<< " output file=" << convert_model_path(dev_null_path)
222+
<< " output file=" << convert_model_path(test_output)
225223
<< " method=log_prob unconstrained_params="
226224
<< convert_model_path(bern_unconstrained_params_short);
227225
std::string cmd = ss.str();

src/test/interface/multi_chain_init_test.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ class CmdStan : public testing::Test {
2121
init3_data = {"src", "test", "test-models", "bern_init2.R"};
2222
init_bad_data = {"src", "test", "test-models", "bern_init_bad.json"};
2323
init_bad_2_data = {"src", "test", "test-models", "bern_init_bad_2.json"};
24-
dev_null_path = {"/dev", "null"};
24+
dummy_output = {"test", "ignored.csv"};
2525
}
2626
std::vector<std::string> bern_model;
27-
std::vector<std::string> dev_null_path;
27+
std::vector<std::string> dummy_output;
2828
std::vector<std::string> bern_data;
2929
std::vector<std::string> init_data;
3030
std::vector<std::string> init2_data;
@@ -38,7 +38,7 @@ TEST_F(CmdStan, multi_chain_single_init_file_good) {
3838
std::stringstream ss;
3939
ss << convert_model_path(bern_model)
4040
<< " data file=" << convert_model_path(bern_data)
41-
<< " output file=" << convert_model_path(dev_null_path)
41+
<< " output file=" << convert_model_path(dummy_output)
4242
<< " init=" << convert_model_path(init_data)
4343
<< " method=sample num_chains=2";
4444
std::string cmd = ss.str();
@@ -50,7 +50,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_good) {
5050
std::stringstream ss;
5151
ss << convert_model_path(bern_model)
5252
<< " data file=" << convert_model_path(bern_data)
53-
<< " output file=" << convert_model_path(dev_null_path)
53+
<< " output file=" << convert_model_path(dummy_output)
5454
<< " init=" << convert_model_path(init2_data)
5555
<< " method=sample num_chains=4";
5656
std::string cmd = ss.str();
@@ -62,7 +62,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_comma_good) {
6262
std::stringstream ss;
6363
ss << convert_model_path(bern_model)
6464
<< " data file=" << convert_model_path(bern_data)
65-
<< " output file=" << convert_model_path(dev_null_path)
65+
<< " output file=" << convert_model_path(dummy_output)
6666
<< " init=" << convert_model_path(init_data) << ","
6767
<< convert_model_path(init2_3_data) << " method=sample num_chains=2";
6868
std::string cmd = ss.str();
@@ -74,7 +74,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_id_good) {
7474
std::stringstream ss;
7575
ss << convert_model_path(bern_model)
7676
<< " data file=" << convert_model_path(bern_data)
77-
<< " output file=" << convert_model_path(dev_null_path)
77+
<< " output file=" << convert_model_path(dummy_output)
7878
<< " init=" << convert_model_path(init2_data) << " id=2"
7979
<< " method=sample num_chains=2";
8080
std::string cmd = ss.str();
@@ -87,7 +87,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_id_bad) {
8787
std::stringstream ss;
8888
ss << convert_model_path(bern_model)
8989
<< " data file=" << convert_model_path(bern_data)
90-
<< " output file=" << convert_model_path(dev_null_path)
90+
<< " output file=" << convert_model_path(dummy_output)
9191
<< " init=" << convert_model_path(init2_data) << " id=4"
9292
<< " method=sample num_chains=3";
9393
std::string cmd = ss.str();
@@ -101,7 +101,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_comma_missing) {
101101
std::stringstream ss;
102102
ss << convert_model_path(bern_model)
103103
<< " data file=" << convert_model_path(bern_data) << " output file="
104-
<< convert_model_path(dev_null_path)
104+
<< convert_model_path(dummy_output)
105105
// second init file does not exist
106106
<< " init=" << convert_model_path(init2_data) << ","
107107
<< convert_model_path(init2_data) << " method=sample num_chains=2";
@@ -115,7 +115,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_comma_wrong_number) {
115115
std::stringstream ss;
116116
ss << convert_model_path(bern_model)
117117
<< " data file=" << convert_model_path(bern_data)
118-
<< " output file=" << convert_model_path(dev_null_path)
118+
<< " output file=" << convert_model_path(dummy_output)
119119
<< " init=" << convert_model_path(init_data) << ","
120120
<< convert_model_path(init2_3_data) << " method=sample num_chains=3";
121121
std::string cmd = ss.str();
@@ -130,7 +130,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_actually_used) {
130130
std::stringstream ss;
131131
ss << convert_model_path(bern_model)
132132
<< " data file=" << convert_model_path(bern_data)
133-
<< " output file=" << convert_model_path(dev_null_path)
133+
<< " output file=" << convert_model_path(dummy_output)
134134
<< " init=" << convert_model_path(init_bad_data)
135135
<< " method=sample num_chains=2";
136136
std::string cmd = ss.str();
@@ -144,7 +144,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_actually_used_comma) {
144144
std::stringstream ss;
145145
ss << convert_model_path(bern_model)
146146
<< " data file=" << convert_model_path(bern_data)
147-
<< " output file=" << convert_model_path(dev_null_path)
147+
<< " output file=" << convert_model_path(dummy_output)
148148
<< " init=" << convert_model_path(init_data) << ","
149149
<< convert_model_path(init_bad_2_data) << " method=sample num_chains=2";
150150
std::string cmd = ss.str();
@@ -157,7 +157,7 @@ TEST_F(CmdStan, multi_chain_multi_init_file_R) {
157157
std::stringstream ss;
158158
ss << convert_model_path(bern_model)
159159
<< " data file=" << convert_model_path(bern_data)
160-
<< " output file=" << convert_model_path(dev_null_path)
160+
<< " output file=" << convert_model_path(dummy_output)
161161
<< " init=" << convert_model_path(init3_data)
162162
<< " method=sample num_chains=4";
163163
std::string cmd = ss.str();

0 commit comments

Comments
 (0)