浏览代码

Add test coverage

Sam Jaffe 4 年之前
父节点
当前提交
06275fe60a
共有 5 个文件被更改,包括 128 次插入6 次删除
  1. 3 0
      .gitmodules
  2. 1 0
      external/scoped_buffer_capture
  3. 10 4
      include/program_args/arguments_impl.hpp
  4. 40 2
      program_args.xcodeproj/project.pbxproj
  5. 74 0
      test/usage_test.cpp

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "external/scoped_buffer_capture"]
+	path = external/scoped_buffer_capture
+	url = ssh://git@gogs.sjaffe.name:3000/sjjaffe/cpp-scoped-buffer-capture.git

+ 1 - 0
external/scoped_buffer_capture

@@ -0,0 +1 @@
+Subproject commit 00e6ddb03d3c2f9fb71ccfee2162401d70b56a6e

+ 10 - 4
include/program_args/arguments_impl.hpp

@@ -7,6 +7,12 @@
 #include "exception.h"
 #include "utilities.h"
 
+#ifndef PROGRAM_ARGS_NOEXIT_ON_HELP
+#define PROGRAM_ARGS_EXIT(X) std::exit(X)
+#else
+#define PROGRAM_ARGS_EXIT(X) (void)X
+#endif
+
 namespace program {
 
 template <typename Impl>
@@ -30,7 +36,7 @@ auto Arguments<Impl>::Argument::operator=(T && value) {
   is_optional = true;
   if (description.size()) {
     using ::program::to_string;
-    description += "Default Value: " + to_string(value);
+    description += "\n    Default Value: " + to_string(value);
   }
   return WithDefault<Argument, T>{*this, std::forward<T>(value)};
 }
@@ -65,7 +71,7 @@ template <typename Impl> Arguments<Impl>::Flag::operator bool() const {
 
 template <typename Impl> auto Arguments<Impl>::Flag::operator=(bool && value) {
   if (description.size()) {
-    description += "Default Value: ";
+    description += "\n    Default Value: ";
     description += (value ? "true" : "false");
   }
   default_value = value;
@@ -98,7 +104,7 @@ template <typename T>
 auto Arguments<Impl>::Option::operator=(T && value) {
   if (description.size()) {
     using ::program::to_string;
-    description += "Default Value: " + to_string(value);
+    description += "\n    Default Value: " + to_string(value);
   }
   return WithDefault<Option, T>{*this, std::forward<T>(value)};
 }
@@ -130,7 +136,7 @@ Arguments<Impl>::Arguments(int argc, char const * const * const argv) {
     char abbrev = arg[1];
     if (arg == "--help") {
       usage();
-      std::exit(0);
+      PROGRAM_ARGS_EXIT(0);
     } else if (arg == "--") {
       arguments.insert(arguments.end(), &argv[i + 1], &argv[argc]);
       break;

+ 40 - 2
program_args.xcodeproj/project.pbxproj

@@ -7,6 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		CD2F0C6425DC9B3500CB394A /* usage_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD2F0C6325DC9B3500CB394A /* usage_test.cpp */; };
 		CD8C5A8925D057900004A6D9 /* GoogleMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDE4F79B25CF316A009E4EC1 /* GoogleMock.framework */; };
 		CD8C5A8B25D057AA0004A6D9 /* options_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD8C5A8A25D057AA0004A6D9 /* options_test.cpp */; };
 		CD8C5AA025D06D0B0004A6D9 /* flag_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD8C5A9F25D06D0B0004A6D9 /* flag_test.cpp */; };
@@ -14,6 +15,13 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+		CD2F0C5B25DC9AE000CB394A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CD2F0C5325DC9AE000CB394A /* scoped_buffer_capture.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CD0C593B20C2D81E00454F82;
+			remoteInfo = scoped_buffer_capture;
+		};
 		CD8C5A7B25D0577E0004A6D9 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = CDE4F78225CF309E009E4EC1 /* Project object */;
@@ -52,6 +60,8 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+		CD2F0C5325DC9AE000CB394A /* scoped_buffer_capture.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = scoped_buffer_capture.xcodeproj; path = external/scoped_buffer_capture/scoped_buffer_capture.xcodeproj; sourceTree = "<group>"; };
+		CD2F0C6325DC9B3500CB394A /* usage_test.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = usage_test.cpp; sourceTree = "<group>"; };
 		CD8C5A7525D0577E0004A6D9 /* program_args-test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "program_args-test.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
 		CD8C5A7925D0577E0004A6D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		CD8C5A8A25D057AA0004A6D9 /* options_test.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = options_test.cpp; sourceTree = "<group>"; };
@@ -87,6 +97,14 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		CD2F0C5425DC9AE000CB394A /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CD2F0C5C25DC9AE000CB394A /* libscoped_buffer_capture.dylib */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
 		CD8C5A7625D0577E0004A6D9 /* program_args-test */ = {
 			isa = PBXGroup;
 			children = (
@@ -124,6 +142,7 @@
 		CDE4F78125CF309E009E4EC1 = {
 			isa = PBXGroup;
 			children = (
+				CD2F0C5325DC9AE000CB394A /* scoped_buffer_capture.xcodeproj */,
 				CDD334A025D200AB008540EE /* README.md */,
 				CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */,
 				CD8C5A8E25D057C00004A6D9 /* include */,
@@ -151,6 +170,7 @@
 				CD8C5AA325D072F50004A6D9 /* argument_test.cpp */,
 				CD8C5A8A25D057AA0004A6D9 /* options_test.cpp */,
 				CD8C5A9F25D06D0B0004A6D9 /* flag_test.cpp */,
+				CD2F0C6325DC9B3500CB394A /* usage_test.cpp */,
 			);
 			path = test;
 			sourceTree = "<group>";
@@ -246,6 +266,10 @@
 					ProductGroup = CDE4F79425CF316A009E4EC1 /* Products */;
 					ProjectRef = CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */;
 				},
+				{
+					ProductGroup = CD2F0C5425DC9AE000CB394A /* Products */;
+					ProjectRef = CD2F0C5325DC9AE000CB394A /* scoped_buffer_capture.xcodeproj */;
+				},
 			);
 			projectRoot = "";
 			targets = (
@@ -256,6 +280,13 @@
 /* End PBXProject section */
 
 /* Begin PBXReferenceProxy section */
+		CD2F0C5C25DC9AE000CB394A /* libscoped_buffer_capture.dylib */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.dylib";
+			path = libscoped_buffer_capture.dylib;
+			remoteRef = CD2F0C5B25DC9AE000CB394A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
 		CDE4F79B25CF316A009E4EC1 /* GoogleMock.framework */ = {
 			isa = PBXReferenceProxy;
 			fileType = wrapper.framework;
@@ -304,6 +335,7 @@
 				CD8C5A8B25D057AA0004A6D9 /* options_test.cpp in Sources */,
 				CD8C5AA025D06D0B0004A6D9 /* flag_test.cpp in Sources */,
 				CD8C5AA425D072F50004A6D9 /* argument_test.cpp in Sources */,
+				CD2F0C6425DC9B3500CB394A /* usage_test.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -413,7 +445,10 @@
 				MTL_FAST_MATH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
-				USER_HEADER_SEARCH_PATHS = include/;
+				USER_HEADER_SEARCH_PATHS = (
+					include/,
+					external/scoped_buffer_capture/include/,
+				);
 			};
 			name = Debug;
 		};
@@ -466,7 +501,10 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				SDKROOT = macosx;
-				USER_HEADER_SEARCH_PATHS = include/;
+				USER_HEADER_SEARCH_PATHS = (
+					include/,
+					external/scoped_buffer_capture/include/,
+				);
 			};
 			name = Release;
 		};

+ 74 - 0
test/usage_test.cpp

@@ -0,0 +1,74 @@
+//
+//  logging_test.cpp
+//  program_args-test
+//
+//  Created by Sam Jaffe on 2/16/21.
+//
+
+#define PROGRAM_ARGS_NOEXIT_ON_HELP
+
+#include "program_args/arguments.h"
+#include "scoped_buffer_capture.h"
+#include "xcode_gtest_helper.h"
+
+using testing::HasSubstr;
+using testing::Not;
+
+template <typename T, size_t N> static T parse(char const * const (&argv)[N]) {
+  return T(N, argv);
+}
+
+template <typename T> auto usage() {
+  scoped_buffer_capture_t cap_cout(std::cout);
+  parse<T>({"", "--help"});
+  return cap_cout.str();
+}
+
+struct ArgNamesTest : program::Arguments<ArgNamesTest> {
+  using program::Arguments<ArgNamesTest>::Arguments;
+  bool dry_run = flag("dry-run");
+  int level = option("level");
+  int port = option("port", 'p');
+};
+
+TEST(ArgNamesTest, PrintsOutBothArgsWhenRelevant) {
+  auto result = usage<ArgNamesTest>();
+  EXPECT_THAT(result, HasSubstr(" --port,-p:"));
+}
+
+TEST(ArgNamesTest, PrintsOutInversionFlag) {
+  auto result = usage<ArgNamesTest>();
+  EXPECT_THAT(result, HasSubstr(" --no-dry-run,--dry-run:"));
+}
+
+TEST(ArgNamesTest, PrintsOutBothSingleNameWithoutAbbrev) {
+  auto result = usage<ArgNamesTest>();
+  EXPECT_THAT(result, HasSubstr(" --level:"));
+}
+
+struct ArgDescTest : program::Arguments<ArgDescTest> {
+  using program::Arguments<ArgDescTest>::Arguments;
+  int port = option("port", "The host port to listen on for web traffic");
+};
+
+TEST(ArgDescTest, PrintsOutBothArgsWhenRelevant) {
+  auto result = usage<ArgDescTest>();
+  EXPECT_THAT(result, HasSubstr(" --port: The host port"));
+}
+
+struct ArgDefValTest : program::Arguments<ArgDefValTest> {
+  using program::Arguments<ArgDefValTest>::Arguments;
+  int level = option("level") = 5;
+  int port = option("port", "The host port to listen on for web traffic") =
+      8080;
+};
+
+TEST(ArgDefValTest, PrintsOutDefaultValueWithDescription) {
+  auto result = usage<ArgDefValTest>();
+  EXPECT_THAT(result, HasSubstr("Default Value: 8080"));
+}
+
+TEST(ArgDefValTest, DoesntAddDefValWithoutDescription) {
+  auto result = usage<ArgDefValTest>();
+  EXPECT_THAT(result, Not(HasSubstr("5")));
+}