GMX_THROW(InvalidInputError(message));
}
}
+ if (sel.hasFlag(efSelection_DisallowEmpty))
+ {
+ if (sel.posCount() == 0)
+ {
+ std::string message = formatString(
+ "Selection '%s' never matches any atoms.",
+ sel.selectionText());
+ GMX_THROW(InvalidInputError(message));
+ }
+ }
}
}
efSelection_OnlyAtoms = 1<<1,
//! Whether ::POS_MASKONLY should be used for output position evaluation.
efSelection_DynamicMask = 1<<2,
+ //! If set, unconditionally empty selections result in compilation errors.
+ efSelection_DisallowEmpty = 1<<3,
//! Whether velocities of output positions should be evaluated.
efSelection_EvaluateVelocities = 1<<5,
//! Whether forces on output positions should be evaluated.
typedef SelectionOptionInfo InfoType;
//! Initializes an option with the given name.
- explicit SelectionOption(const char *name) : MyBase(name) { }
+ explicit SelectionOption(const char *name)
+ : MyBase(name), selectionFlags_(efSelection_DisallowEmpty)
+ {
+ }
/*! \brief
* Request velocity evaluation for output positions.
*/
MyClass &dynamicMask()
{ selectionFlags_.set(efSelection_DynamicMask); return me(); }
+ /*! \brief
+ * Allow specifying an unconditionally empty selection for this option.
+ *
+ * If this option is not set, selections that are unconditionally empty
+ * (i.e., can never match any atoms) result in errors.
+ * Note that even without this option, it is still possible that a
+ * dynamic selection evaluates to zero atoms for some frames.
+ */
+ MyClass &allowEmpty()
+ { selectionFlags_.clear(efSelection_DisallowEmpty); return me(); }
private:
// Disable possibility to allow multiple occurrences, since it isn't
}
+TEST_F(SelectionOptionTest, ChecksEmptySelections)
+{
+ gmx::Selection sel;
+ using gmx::SelectionOption;
+ ASSERT_NO_THROW_GMX(options_.addOption(
+ SelectionOption("sel").store(&sel)));
+ setManager();
+
+ gmx::OptionsAssigner assigner(&options_);
+ EXPECT_NO_THROW_GMX(assigner.start());
+ ASSERT_NO_THROW_GMX(assigner.startOption("sel"));
+ EXPECT_NO_THROW_GMX(assigner.appendValue("none"));
+ EXPECT_NO_THROW_GMX(assigner.finishOption());
+ EXPECT_NO_THROW_GMX(assigner.finish());
+ EXPECT_NO_THROW_GMX(options_.finish());
+
+ EXPECT_THROW_GMX(sc_.compile(), gmx::InvalidInputError);
+}
+
+
TEST_F(SelectionOptionTest, HandlesTooManySelections)
{
gmx::Selection sel;