git.fiddlerwoaroof.com
Browse code

merge branch 'user'

Greg Wiley authored on 22/04/2017 00:05:09
Showing 8 changed files
... ...
@@ -1,8 +1,9 @@
1 1
 CXXFLAGS += -fPIC -fno-stack-protector -std=c++14
2 2
 CFLAGS += -fPIC -fno-stack-protector
3 3
 
4
-OBJS = dual_control.o request.o dual_control_integrate.o validator.o conversation.o
5
-TESTS = dual_control_test validator_test conversation_test request_test
4
+OBJS = dual_control.o request.o dual_control_integrate.o validator.o conversation.o user.o \
5
+	   sys_unistd.o sys_pwd.o
6
+TESTS = dual_control_test validator_test conversation_test request_test user_test
6 7
 TESTOBJS = $(patsubst %,%.o,$(TESTS))
7 8
 SRCS := $(OBJS:.o=.cc) $(TESTOBJS:.o=.cc)
8 9
 
9 10
new file mode 100644
... ...
@@ -0,0 +1,35 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
12
+#include "sys_pwd.h"
13
+
14
+#include <pwd.h>
15
+
16
+namespace
17
+{
18
+class impl : public pwd_ifc
19
+{
20
+public:
21
+    int getpwnam_r (const char *user_name, passwd *out, char *buffer,
22
+                    size_t buffer_sz, passwd **result)
23
+    {
24
+        return ::getpwnam_r (user_name, out, buffer, buffer_sz, result);
25
+    }
26
+
27
+};
28
+static pwd system_pwd (pwd::delegate (new impl));
29
+}
30
+
31
+pwd pwd::system()
32
+{
33
+    return system_pwd;
34
+}
35
+
0 36
new file mode 100644
... ...
@@ -0,0 +1,49 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
12
+#ifndef _SYS_PWD_H
13
+#define _SYS_PWD_H
14
+
15
+#include <memory>
16
+#include <pwd.h>
17
+
18
+class pwd_ifc
19
+{
20
+public:
21
+    virtual int getpwnam_r (const char *user_name, passwd *out, char *buffer,
22
+                            size_t buffer_sz, passwd **result)
23
+    {
24
+        *result = 0;
25
+        return 0;
26
+    };
27
+};
28
+
29
+class pwd : public pwd_ifc
30
+{
31
+public:
32
+    typedef std::shared_ptr<pwd_ifc> delegate;
33
+
34
+private:
35
+    delegate delegate_;
36
+
37
+public:
38
+    pwd (const delegate delegate) : delegate_ (delegate) {}
39
+    pwd() : delegate_ (delegate (new pwd_ifc)) {}
40
+    int getpwnam_r (const char *user_name, passwd *out, char *buffer,
41
+                    size_t buffer_sz, passwd **result)
42
+    {
43
+        return delegate_-> getpwnam_r (user_name, out, buffer, buffer_sz, result);
44
+    }
45
+    static pwd system();
46
+};
47
+
48
+#endif
49
+
0 50
new file mode 100644
... ...
@@ -0,0 +1,32 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
12
+#include "sys_unistd.h"
13
+#include <unistd.h>
14
+
15
+namespace
16
+{
17
+class impl : public unistd_ifc
18
+{
19
+public:
20
+    long int sysconf (int name)
21
+    {
22
+        return ::sysconf (name);
23
+    }
24
+};
25
+static unistd sys_unistd (unistd::delegate (new impl));
26
+}
27
+
28
+unistd unistd::system()
29
+{
30
+    return sys_unistd;
31
+}
32
+
0 33
new file mode 100644
... ...
@@ -0,0 +1,47 @@
1
+/* Copyright (C) CJ Affiliate
2
+ *
3
+ * You may use, distribute and modify this code under  the
4
+ * terms of the  GNU General Public License  version 2  or
5
+ * later.
6
+ *
7
+ * You should have received a copy of the license with this
8
+ * file. If not, you will find a copy in the "LICENSE" file
9
+ * at https://github.com/cjdev/dual-control.
10
+ */
11
+
12
+#ifndef _SYS_UNISTD_H_
13
+#define _SYS_UNISTD_H_
14
+
15
+#include <memory>
16
+
17
+#include <unistd.h>
18
+
19
+class unistd_ifc
20
+{
21
+public:
22
+    virtual long int sysconf (int name)
23
+    {
24
+        return -1;
25
+    }
26
+};
27
+
28
+class unistd : public unistd_ifc
29
+{
30
+public:
31
+    typedef std::shared_ptr<unistd_ifc> delegate;
32
+
33
+private:
34
+    delegate delegate_;
35
+
36
+public:
37
+    unistd (delegate delegate): delegate_ (delegate) {}
38
+    unistd() : delegate_ (delegate (new unistd_ifc)) {}
39
+    long int sysconf (int name)
40
+    {
41
+        return delegate_->sysconf (name);
42
+    }
43
+    static unistd system();
44
+};
45
+
46
+#endif
47
+
... ...
@@ -11,25 +11,44 @@
11 11
 
12 12
 #include <memory>
13 13
 #include <vector>
14
-#include <string>
15
-#include <pwd.h>
16
-#include <unistd.h>
17
-#include <iostream>
18 14
 
19 15
 #include "user.h"
20
-#include "test_support.h"
16
+#include "sys_unistd.h"
17
+#include "sys_pwd.h"
21 18
 
22
-user::user (struct passwd *sys_info) : info (sys_info)
19
+namespace
23 20
 {
21
+class directory_impl : public directory_ifc
22
+{
23
+private:
24
+    unistd unistd_;
25
+    pwd pwd_;
26
+public:
27
+    directory_impl (unistd &unistd, pwd &pwd) : unistd_ (unistd), pwd_ (pwd) {}
28
+    std::vector<user> find_user (const std::string &user_name)
29
+    {
30
+        std::vector<char> buffer (unistd_.sysconf (_SC_GETPW_R_SIZE_MAX));
31
+        passwd sys_passwd;
32
+        passwd *found_passwd (0);
33
+        int result = pwd_.getpwnam_r (user_name.c_str(), &sys_passwd,
34
+                                      buffer.data(), buffer.size(), &found_passwd);
35
+        std::vector<user> return_value;
36
+
37
+        if (!result && found_passwd) {
38
+            return_value.push_back (user());
39
+        }
40
+
41
+        return return_value;
42
+    }
43
+};
24 44
 }
25 45
 
26
-std::string user::home_directory()
46
+directory directory::create (unistd &unistd, pwd &pwd)
27 47
 {
28
-    return info->pw_dir;
48
+    return directory (delegate (new directory_impl (unistd, pwd)));
29 49
 }
30 50
 
31
-// concrete user implementation
32
-
51
+/*
33 52
 class concrete_user : public user
34 53
 {
35 54
 private:
... ...
@@ -65,4 +84,5 @@ const std::shared_ptr<user> create_user (const std::string &user_name)
65 84
 
66 85
     return rval;
67 86
 }
87
+*/
68 88
 
... ...
@@ -14,7 +14,9 @@
14 14
 #include <vector>
15 15
 #include <string>
16 16
 #include <memory>
17
-#include <pwd.h>
17
+
18
+#include "sys_unistd.h"
19
+#include "sys_pwd.h"
18 20
 
19 21
 class user_ifc
20 22
 {
... ...
@@ -43,19 +45,20 @@ public:
43 45
 
44 46
 class directory : public directory_ifc
45 47
 {
48
+public:
49
+    typedef std::shared_ptr<directory_ifc> delegate;
46 50
 private:
47
-    std::shared_ptr<directory_ifc> delegate_;
51
+    delegate delegate_;
48 52
 public:
49
-    directory (std::shared_ptr<directory_ifc> delegate) : delegate_
53
+    directory (delegate delegate) : delegate_
50 54
         (delegate) {}
51
-    directory() : directory (std::shared_ptr<directory_ifc>
52
-                                 (new directory_ifc)) {}
55
+    directory() : directory (delegate (new directory_ifc)) {}
53 56
     std::vector<user> find_user (const std::string &user_name)
54 57
     {
55 58
         return delegate_->find_user (user_name);
56 59
     }
57 60
 
58
-    static directory create();
61
+    static directory create (unistd &unistd, pwd &pwd);
59 62
 };
60 63
 
61 64
 #endif
... ...
@@ -9,87 +9,162 @@
9 9
  * at https://github.com/cjdev/dual-control.
10 10
  */
11 11
 
12
-#include <memory>
13
-#include <iostream>
14 12
 #include "user.h"
15 13
 #include "test_util.h"
14
+#include "sys_pwd.h"
15
+#include "sys_unistd.h"
16 16
 
17
-bool gets_home_directory()
17
+class fake_pwd : public pwd_ifc
18
+{
19
+private:
20
+    std::string expected_user_name_;
21
+public:
22
+    fake_pwd (const std::string expected_user_name) : expected_user_name_
23
+        (expected_user_name) {}
24
+    int getpwnam_r (const char *user_name, passwd *out, char *buffer,
25
+                    size_t buffer_sz, passwd **result)
26
+    {
27
+        if (expected_user_name_ == user_name)  {
28
+            *result = out;
29
+        } else {
30
+            *result = 0;
31
+        }
32
+
33
+        return 0;
34
+    }
35
+};
36
+
37
+class match_buffer_pwd : public pwd_ifc
38
+{
39
+private:
40
+    long int expected_buffer_sz_;
41
+public:
42
+    match_buffer_pwd (long int buffer_sz) : expected_buffer_sz_ (buffer_sz) {}
43
+    int getpwnam_r (const char *user_name, passwd *out, char *buffer,
44
+                    size_t buffer_sz, passwd **result)
45
+    {
46
+
47
+        if (expected_buffer_sz_ == buffer_sz && buffer != 0) {
48
+            *result = out;
49
+        } else {
50
+            *result = 0;
51
+        }
52
+
53
+        return 0;
54
+    }
55
+};
56
+
57
+class stub_pwnam_err_pwd : public pwd_ifc
58
+{
59
+public:
60
+    int getpwnam_r (const char *user_name, passwd *out, char *buffer,
61
+                    size_t buffer_sz, passwd **result)
62
+    {
63
+        *result = out;
64
+        return 3;
65
+    }
66
+
67
+};
68
+
69
+class fake_unistd : public unistd_ifc
70
+{
71
+private:
72
+    int expected_name_;
73
+    long int return_value_;
74
+public:
75
+    fake_unistd (int expected_name, long int return_value = 0)
76
+        : expected_name_ (expected_name),
77
+          return_value_ (return_value) {}
78
+    long int sysconf (int name)
79
+    {
80
+        if (name == expected_name_) {
81
+            return return_value_;
82
+        }
83
+
84
+        return -1;
85
+    }
86
+};
87
+
88
+int find_user_happy()
18 89
 {
19 90
     //given
20
-    const char *expected_home_directory = "home/msmith";
21
-    struct passwd test_passwd;
22
-    test_passwd.pw_dir = const_cast<char *> (expected_home_directory);
23
-    user test_user (&test_passwd);
91
+    std::string user_name ("user");
92
+    pwd test_pwd (pwd::delegate (new fake_pwd (user_name)));
93
+    unistd test_unistd (unistd::delegate (new fake_unistd (
94
+            _SC_GETPW_R_SIZE_MAX)));
95
+    directory directory (directory::create (test_unistd, test_pwd));
24 96
 
25 97
     //when
26
-    std::string actual_home_directory = test_user.home_directory();
98
+    std::vector<user> results = directory.find_user (user_name);
27 99
 
28 100
     //then
29
-    check (expected_home_directory == actual_home_directory,
30
-           "directories do not match");
31
-    return expected_home_directory == actual_home_directory;
101
+    check (!results.empty(), "user should have been found");
102
+    succeed();
32 103
 }
33 104
 
34
-std::shared_ptr<struct passwd> fake_passwd;
35
-int fake_getpwnam_r (const char *nam, struct passwd *pwd, char *buffer,
36
-                     size_t bufsize, struct passwd **result)
105
+int user_not_found()
37 106
 {
38
-    if (fake_passwd) {
39
-        *pwd = *fake_passwd;
40
-        *result = pwd;
41
-        return 0;
42
-    }
107
+    //given
108
+    pwd test_pwd (pwd::delegate (new fake_pwd ("user")));
109
+    unistd test_unistd (unistd::delegate (new fake_unistd (
110
+            _SC_GETPW_R_SIZE_MAX)));
111
+    directory directory (directory::create (test_unistd, test_pwd));
112
+
113
+    //when
114
+    std::vector<user> results = directory.find_user ("not_user");
115
+
116
+    //then
117
+    check (results.empty(), "user should not have been found");
118
+    succeed();
43 119
 
44
-    return -1;
45 120
 }
46 121
 
47
-bool create_user_succeeds()
122
+int find_user_passes_buffer_and_size()
48 123
 {
49
-    // given
50
-    std::string username ("msmith");
51
-    std::string home_directory ("this is my home");
52
-    fake_passwd.reset (new struct passwd);
53
-    fake_passwd->pw_dir = const_cast<char *> (home_directory.c_str());
124
+    //given
125
+    long int buffer_sz = 5976;
126
+    unistd test_unistd (unistd::delegate (new fake_unistd (_SC_GETPW_R_SIZE_MAX,
127
+                                          buffer_sz)));
128
+    pwd match_pwd (pwd::delegate (new match_buffer_pwd (buffer_sz)));
129
+    directory directory (directory::create (test_unistd, match_pwd));
54 130
 
55
-    // when
56
-    std::shared_ptr<user> user (create_user (username));
131
+    //when
132
+    std::vector<user> results = directory.find_user ("does_not_matter");
57 133
 
58 134
     // then
59
-    check (user, "user should be returned");
60
-    check (user->home_directory() == home_directory,
61
-           "home directory does not match");
62
-
135
+    check (!results.empty(), "match failed");
63 136
     succeed();
64
-
65 137
 }
66 138
 
67
-bool create_user_nonexistent()
139
+int find_user_fails_on_pwnam_r_error_and_result_ok()
68 140
 {
69
-    // given
70
-    std::string username ("msmith");
141
+    //given
142
+    unistd test_unistd (unistd::delegate (new fake_unistd (
143
+            _SC_GETPW_R_SIZE_MAX)));
144
+    pwd stub_pwd (pwd::delegate (new stub_pwnam_err_pwd));
145
+    directory directory (directory::create (test_unistd, stub_pwd));
71 146
 
72
-    // when
73
-    std::shared_ptr<user> user (create_user (username));
147
+    //when
148
+    std::vector<user> results = directory.find_user ("does_not_matter");
74 149
 
75 150
     // then
76
-    check (!user, "no user should be returned");
77
-
151
+    check (results.empty(), "did not check return");
78 152
     succeed();
79 153
 }
80 154
 
81 155
 RESET_VARS_START
82
-fake_passwd.reset ((struct passwd *)0);
83 156
 RESET_VARS_END
84 157
 
85 158
 int run_tests()
86 159
 {
87
-    test (gets_home_directory);
88
-    test (create_user_succeeds);
89
-    test (create_user_nonexistent);
160
+    test (find_user_happy);
161
+    test (user_not_found);
162
+    test (find_user_passes_buffer_and_size);
163
+    test (find_user_fails_on_pwnam_r_error_and_result_ok);
90 164
     succeed();
91 165
 }
92
-int main (int argc, char *argv[])
166
+
167
+int main (int argc, char **argv)
93 168
 {
94 169
     return !run_tests();
95 170
 }