Implement --set-bucket and --delete-bucket in Cyad 83/32183/7
authorAleksander Zdyb <a.zdyb@samsung.com>
Mon, 15 Dec 2014 12:49:46 +0000 (13:49 +0100)
committerPawel Wieczorek <p.wieczorek2@samsung.com>
Mon, 29 Dec 2014 14:58:01 +0000 (15:58 +0100)
Change-Id: I61065bb8364d8cb33821c8a7be20a4b756522b43

src/cyad/CommandlineParser/CyadCommandlineParser.cpp
src/cyad/CommandlineParser/CyadCommandlineParser.h
src/cyad/CommandlineParser/PolicyParsingException.h [new file with mode: 0644]
test/cyad/commandline.cpp
test/cyad/commandline_errors.cpp

index 845f1ef..713b506 100644 (file)
@@ -24,6 +24,9 @@
 #include <getopt.h>
 #include <map>
 #include <sstream>
+#include <string>
+
+#include <cyad/CommandlineParser/PolicyParsingException.h>
 
 #include "CyadCommandlineParser.h"
 
@@ -32,12 +35,29 @@ namespace Cynara {
 namespace CyadCmdlineArgs {
     const char HELP = 'h';
     const char * const HELP_LONG = "help";
+
+    const char SET_BUCKET = 'b';
+    const char * const SET_BUCKET_LONG = "set-bucket";
+
+    const char DELETE_BUCKET = 'd';
+    const char * const DELETE_BUCKET_LONG = "delete-bucket";
+
+    const char POLICY = 'p';
+    const char * const POLICY_LONG = "policy";
+
+    const char METADATA = 'm';
+    const char * const METADATA_LONG = "metadata";
 }
 
 namespace CyadCmdlineErrors {
     const char * const UNKNOWN_ERROR = "Unknown error";
     const char * const NO_OPTION = "No option specified";
     const char * const UNKNOWN_OPTION = "Unknown option";
+    const char * const UNKNOWN_OPTION_SET_BUCKET = "Unknown option in --set-bucket";
+    const char * const UNKNOWN_OPTION_DELETE_BUCKET = "Unknown option in --delete-bucket";
+    const char * const NO_POLICY = "No --policy specified";
+    const char * const NO_BUCKET = "No bucket specified";
+    const char * const INVALID_POLICY = "Invalid --policy option";
 }
 
 CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv)
@@ -49,33 +69,124 @@ std::shared_ptr<CyadCommand> CyadCommandlineParser::parseMain(void) {
     namespace Args = CyadCmdlineArgs;
 
     const struct option long_options[] = {
-        { Args::HELP_LONG, no_argument, nullptr, Args::HELP },
+        { Args::HELP_LONG,          no_argument,       nullptr, Args::HELP },
+        { Args::SET_BUCKET_LONG,    required_argument, nullptr, Args::SET_BUCKET },
+        { Args::DELETE_BUCKET_LONG, required_argument, nullptr, Args::DELETE_BUCKET },
         { nullptr, 0, nullptr, 0 }
     };
 
     optind = 0; // On entry to `getopt', zero means this is the first call; initialize.
     int opt;
     std::stringstream optstr;
-    optstr << ":" << Args::HELP;
+    optstr << ":" << Args::HELP
+           << Args::SET_BUCKET << ":"
+           << Args::DELETE_BUCKET << ":";
 
     while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
         switch (opt) {
-        case Args::HELP:
-            return std::make_shared<HelpCyadCommand>();
+            case Args::HELP:
+                return std::make_shared<HelpCyadCommand>();
 
-        case '?': // Unknown option
-            return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
+            case Args::SET_BUCKET:
+                return parseSetBucket(optarg);
 
-        case ':': // Missing argument
-            // Shall never happen, but let's just make compiler happy.
-            return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_ERROR);
+            case Args::DELETE_BUCKET:
+                return parseDeleteBucket(optarg);
 
-        default:
-            return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
+            case '?': // Unknown option
+                return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
+
+            case ':': // Missing argument
+                switch (optopt) {
+                    case Args::SET_BUCKET:
+                    case Args::DELETE_BUCKET:
+                        return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::NO_BUCKET);
+                }
+                // Shall never happen, but let's just make compiler happy.
+                return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_ERROR);
+
+            default:
+                return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
         }
     }
 
     return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::NO_OPTION);
 }
 
+std::shared_ptr<CyadCommand> CyadCommandlineParser::parseSetBucket(const std::string &bucketId) {
+    namespace Args = CyadCmdlineArgs;
+    namespace Errors = CyadCmdlineErrors;
+
+    const struct option long_options[] = {
+        { Args::POLICY_LONG, required_argument, nullptr, Args::POLICY },
+        { Args::METADATA_LONG, required_argument, nullptr, Args::METADATA },
+        { nullptr, 0, nullptr, 0 }
+    };
+
+    std::string policy;
+    std::string metadata;
+
+    int opt;
+    std::stringstream optstr;
+    optstr << ":"
+           << Args::POLICY << ":"
+           << Args::METADATA << ":";
+
+    while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
+        switch(opt) {
+        case Args::POLICY:
+            policy = optarg;
+            break;
+        case Args::METADATA:
+            metadata = optarg;
+            break;
+        default:
+            return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_SET_BUCKET);
+        }
+    }
+
+    if (policy.empty())
+        return std::make_shared<ErrorCyadCommand>(Errors::NO_POLICY);
+
+    try {
+        auto policyType = parsePolicyType(policy);
+        return std::make_shared<SetBucketCyadCommand>(bucketId, PolicyResult(policyType, metadata));
+    } catch (const PolicyParsingException &) {
+        return std::make_shared<ErrorCyadCommand>(Errors::INVALID_POLICY);
+    }
+}
+
+std::shared_ptr<CyadCommand> CyadCommandlineParser::parseDeleteBucket(const std::string &bucketId) {
+    namespace Errors = CyadCmdlineErrors;
+
+    // Expect no additional options
+    const struct option long_options[] = {
+        { nullptr, 0, nullptr, 0 }
+    };
+
+    if (getopt_long(m_argc, m_argv, ":", long_options, nullptr) == -1) {
+        return std::make_shared<DeleteBucketCyadCommand>(bucketId);
+    } else {
+        return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_DELETE_BUCKET);
+    }
+}
+
+PolicyType CyadCommandlineParser::parsePolicyType(const std::string &rawPolicy) {
+    if (rawPolicy == "DENY")
+        return CYNARA_ADMIN_DENY;
+    if (rawPolicy == "NONE")
+        return CYNARA_ADMIN_NONE;
+    if (rawPolicy == "BUCKET")
+        return CYNARA_ADMIN_BUCKET;
+    if (rawPolicy == "ALLOW")
+        return CYNARA_ADMIN_ALLOW;
+
+    // If base for std::stoi is set to 0, it detects base by itself from the format of the sequence
+    try {
+        return std::stoi(rawPolicy, nullptr, 0);
+    } catch (const std::logic_error &) {
+        throw PolicyParsingException();
+    }
+}
+
 } /* namespace Cynara */
index 7b30348..4b629c4 100644 (file)
@@ -32,12 +32,29 @@ namespace Cynara {
 namespace CyadCmdlineArgs {
     extern const char HELP;
     extern const char * const HELP_LONG;
+
+    extern const char SET_BUCKET;
+    extern const char * const SET_BUCKET_LONG;
+
+    extern const char DELETE_BUCKET;
+    extern const char * const DELETE_BUCKET_LONG;
+
+    extern const char POLICY;
+    extern const char * const POLICY_LONG;
+
+    extern const char METADATA;
+    extern const char * const METADATA_LONG;
 }
 
 namespace CyadCmdlineErrors {
     extern const char * const UNKNOWN_ERROR;
     extern const char * const NO_OPTION;
     extern const char * const UNKNOWN_OPTION;
+    extern const char * const UNKNOWN_OPTION_SET_BUCKET;
+    extern const char * const UNKNOWN_OPTION_DELETE_BUCKET;
+    extern const char * const NO_POLICY;
+    extern const char * const NO_BUCKET;
+    extern const char * const INVALID_POLICY;
 }
 
 class CyadCommandlineParser {
@@ -46,6 +63,11 @@ public:
     virtual ~CyadCommandlineParser();
 
     std::shared_ptr<CyadCommand> parseMain(void);
+    static PolicyType parsePolicyType(const std::string &rawPolicy);
+
+protected:
+    std::shared_ptr<CyadCommand> parseSetBucket(const std::string &bucketId);
+    std::shared_ptr<CyadCommand> parseDeleteBucket(const std::string &bucketId);
 
 private:
     int m_argc;
diff --git a/src/cyad/CommandlineParser/PolicyParsingException.h b/src/cyad/CommandlineParser/PolicyParsingException.h
new file mode 100644 (file)
index 0000000..958d44e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+/**
+ * @file        src/cyad/CommandlineParser/PolicyParsingException.h
+ * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version     1.0
+ * @brief       PolicyParsingException
+ */
+
+#ifndef SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_
+#define SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_
+
+#include <exceptions/Exception.h>
+
+namespace Cynara {
+
+class PolicyParsingException : public Exception {
+public:
+    PolicyParsingException() {
+        m_message = "Invalid policy";
+    }
+
+    virtual const std::string &message(void) const {
+        return m_message;
+    }
+
+private:
+    std::string m_message;
+};
+
+} /* namespace Cynara */
+
+#endif /* SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_ */
index 620cf28..31b0771 100644 (file)
@@ -38,3 +38,70 @@ TEST_F(CyadCommandlineTest, help) {
     auto result = std::dynamic_pointer_cast<Cynara::HelpCyadCommand>(parser.parseMain());
     ASSERT_NE(nullptr, result);
 }
+
+TEST_F(CyadCommandlineTest, deleteBucket) {
+    prepare_argv({ "./cyad", "--delete-bucket=bucket" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::DeleteBucketCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("bucket", result->bucketId());
+}
+
+TEST_F(CyadCommandlineTest, setBucket) {
+    prepare_argv({ "./cyad", "--set-bucket=bucket", "--policy=42" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetBucketCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("bucket", result->bucketId());
+    ASSERT_EQ(42, result->policyResult().policyType());
+    ASSERT_TRUE(result->policyResult().metadata().empty());
+}
+
+TEST_F(CyadCommandlineTest, setBucketWithMetadata) {
+    const std::string ultimateAnswer = "Answer to The Ultimate Question of Life,"
+                                       " the Universe, and Everything";
+
+    prepare_argv({ "./cyad", "--set-bucket=adams", "--policy=42", "--metadata=" + ultimateAnswer });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+    auto result = std::dynamic_pointer_cast<Cynara::SetBucketCyadCommand>(parser.parseMain());
+    ASSERT_NE(nullptr, result);
+    ASSERT_EQ("adams", result->bucketId());
+    ASSERT_EQ(42, result->policyResult().policyType());
+    ASSERT_EQ(ultimateAnswer, result->policyResult().metadata());
+}
+
+TEST_F(CyadCommandlineTest, parsePolicyTypeBase10) {
+    auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType {
+        return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy);
+    };
+
+    ASSERT_EQ(CYNARA_ADMIN_DENY,   parsePolicyType("0"));
+    ASSERT_EQ(CYNARA_ADMIN_NONE,   parsePolicyType("1"));
+    ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("65534"));
+    ASSERT_EQ(CYNARA_ADMIN_ALLOW,  parsePolicyType("65535"));
+}
+
+TEST_F(CyadCommandlineTest, parsePolicyTypeBase16) {
+    auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType {
+        return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy);
+    };
+
+    ASSERT_EQ(CYNARA_ADMIN_DENY,   parsePolicyType("0x0"));
+    ASSERT_EQ(CYNARA_ADMIN_NONE,   parsePolicyType("0x1"));
+    ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("0xFFFE"));
+    ASSERT_EQ(CYNARA_ADMIN_ALLOW,  parsePolicyType("0xFFFF"));
+}
+
+TEST_F(CyadCommandlineTest, parsePolicyTypeHuman) {
+    auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType {
+        return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy);
+    };
+
+    ASSERT_EQ(CYNARA_ADMIN_DENY,   parsePolicyType("DENY"));
+    ASSERT_EQ(CYNARA_ADMIN_NONE,   parsePolicyType("NONE"));
+    ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("BUCKET"));
+    ASSERT_EQ(CYNARA_ADMIN_ALLOW,  parsePolicyType("ALLOW"));
+}
index 5326119..5aa358f 100644 (file)
@@ -48,3 +48,45 @@ TEST_F(CyadCommandlineTest, unknownOption) {
     Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
     ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION, parser.parseMain());
 }
+
+TEST_F(CyadCommandlineTest, deleteBucketNoBucket) {
+    prepare_argv({ "./cyad", "--delete-bucket" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, deleteBucketUnknownOption) {
+    prepare_argv({ "./cyad", "--delete-bucket=bucket", "--unknown" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_DELETE_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketNoBucket) {
+    prepare_argv({ "./cyad", "--set-bucket" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketNoPolicy) {
+    prepare_argv({ "./cyad", "--set-bucket=bucket" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketInvalidPolicy) {
+    prepare_argv({ "./cyad", "--set-bucket=bucket", "--policy=NaN" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::INVALID_POLICY, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketUnknownOption) {
+    prepare_argv({ "./cyad", "--set-bucket=bucket", "--unknown", "--policy=42" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_SET_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketMetadataNoPolicy) {
+    prepare_argv({ "./cyad", "--set-bucket=bucket", "--metadata=some-meta" });
+    Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+    ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain());
+}