From: Hans Fugal <fugalh@fb.com> Date: Mon, 7 Apr 2014 16:57:42 +0000 (-0700) Subject: (wangle) codegen then() variant tests X-Git-Tag: v0.22.0~617 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=64d0f9a3abd94ac3c0296fab92c8cb6dc83b4763;p=folly.git (wangle) codegen then() variant tests Summary: When all the variants I am dreaming of work, there's a little more than 100 tests generated. Test Plan: fbmake runtests Reviewed By: hannesr@fb.com FB internal diff: D1258754 --- diff --git a/folly/wangle/test/Thens.cpp b/folly/wangle/test/Thens.cpp new file mode 100644 index 00000000..633c9252 --- /dev/null +++ b/folly/wangle/test/Thens.cpp @@ -0,0 +1,19 @@ +// This file is @generated by thens.rb + +#include "Thens.h" + +TEST(Future, thenVariants) { + SomeClass anObject; + Executor* anExecutor; + + {Future<B> f = someFuture<A>().then(aFunction<Future<B>, Try<A>&&>);} + {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>&&>);} + {Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, Try<A>&&>);} + {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>&&>());} + {Future<B> f = someFuture<A>().then([&](Try<A>&&){return someFuture<B>();});} + {Future<B> f = someFuture<A>().then(aFunction<B, Try<A>&&>);} + {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&&>);} + {Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, Try<A>&&>);} + {Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>&&>());} + {Future<B> f = someFuture<A>().then([&](Try<A>&&){return B();});} +} diff --git a/folly/wangle/test/Thens.h b/folly/wangle/test/Thens.h new file mode 100644 index 00000000..455f2d6f --- /dev/null +++ b/folly/wangle/test/Thens.h @@ -0,0 +1,106 @@ +/* + * Copyright 2014 Facebook, Inc. + * + * 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. + */ + +#pragma once +#include <gtest/gtest.h> +#include <memory> +#include "folly/wangle/Future.h" +#include "folly/wangle/Executor.h" + +using namespace folly::wangle; +using namespace std; +using namespace testing; + +typedef unique_ptr<int> A; +struct B {}; + +template <class T> +using EnableIfFuture = typename std::enable_if<isFuture<T>::value>::type; + +template <class T> +using EnableUnlessFuture = typename std::enable_if<!isFuture<T>::value>::type; + +template <class T> +Future<T> someFuture() { + return makeFuture(T()); +} + +template <class Ret, class... Params, typename = void> +Ret aFunction(Params...); + +template <class Ret, class... Params> +typename std::enable_if<isFuture<Ret>::value, Ret>::type +aFunction(Params...) { + typedef typename Ret::value_type T; + return makeFuture(T()); +} + +template <class Ret, class... Params> +typename std::enable_if<!isFuture<Ret>::value, Ret>::type +aFunction(Params...) { + return Ret(); +} + +template <class Ret, class... Params> +std::function<Ret(Params...)> +aStdFunction(typename std::enable_if<!isFuture<Ret>::value, bool>::type = false) { + return [](Params...) -> Ret { return Ret(); }; +} + +template <class Ret, class... Params> +std::function<Ret(Params...)> +aStdFunction(typename std::enable_if<isFuture<Ret>::value, bool>::type = true) { + typedef typename Ret::value_type T; + return [](Params...) -> Future<T> { return makeFuture(T()); }; +} + +class SomeClass { + B b; +public: + template <class Ret, class... Params> + static Ret aStaticMethod(Params...); + + template <class Ret, class... Params> + static + typename std::enable_if<!isFuture<Ret>::value, Ret>::type + aStaticMethod(Params...) { + return Ret(); + } + + template <class Ret, class... Params> + static + typename std::enable_if<isFuture<Ret>::value, Ret>::type + aStaticMethod(Params...) { + typedef typename Ret::value_type T; + return makeFuture(T()); + } + + template <class Ret, class... Params> + Ret aMethod(Params...); + + template <class Ret, class... Params> + typename std::enable_if<!isFuture<Ret>::value, Ret>::type + aMethod(Params...) { + return Ret(); + } + + template <class Ret, class... Params> + typename std::enable_if<isFuture<Ret>::value, Ret>::type + aMethod(Params...) { + typedef typename Ret::value_type T; + return makeFuture(T()); + } +}; diff --git a/folly/wangle/test/thens.rb b/folly/wangle/test/thens.rb new file mode 100755 index 00000000..2f073530 --- /dev/null +++ b/folly/wangle/test/thens.rb @@ -0,0 +1,72 @@ +#!/usr/bin/env ruby + +# An exercise in combinatorics. +# (ordinary/static function, member function, std::function, lambda) +# X +# returns (Future<R>, R) +# X +# accepts (Try<T>&&, Try<T> const&, Try<T>, T&&, T const&, T, nothing) + +def test(*args) + args = args.join(", ") + [ + "{Future<B> f = someFuture<A>().then(#{args});}", + #"{Future<B> f = makeFuture(A()).then(#{args}, anExecutor);}", + ] +end + +def retval(ret) + { + "Future<B>" => "someFuture<B>()", + "Try<B>" => "Try<B>(B())", + "B" => "B()" + }[ret] +end + +return_types = [ + "Future<B>", + "B", + #"Try<B>", +] +param_types = [ + "Try<A>&&", + #"Try<A> const&", + #"Try<A>", + #"Try<A>&", + #"A&&", + #"A const&", + #"A", + #"A&", + #"", + ] + +tests = ( + return_types.map { |ret| + param_types.map { |param| + both = "#{ret}, #{param}" + [ + ["aFunction<#{both}>"], + ["&SomeClass::aStaticMethod<#{both}>"], + # TODO switch these around (std::bind-style) + ["&anObject", "&SomeClass::aMethod<#{both}>"], + ["aStdFunction<#{both}>()"], + ["[&](#{param}){return #{retval(ret)};}"], + ] + } + }.flatten(2) + [ + #[""], + ] +).map {|a| test(a)}.flatten + +print <<EOF +// This file is #{"@"}generated by thens.rb + +#include "Thens.h" + +TEST(Future, thenVariants) { + SomeClass anObject; + Executor* anExecutor; + + #{tests.join("\n ")} +} +EOF