mirror of https://github.com/oxen-io/lokinet
Merge remote-tracking branch 'origin/staging' into staging
commit
c31c8ce889
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
rm -fr loki*/tmp-nodes
|
||||
rm loki*/profile.dat
|
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
# copy a lokinet binary into this cluster
|
||||
cp ../../lokinet .
|
||||
# generate default config file
|
||||
./lokinet -g lokinet.ini
|
||||
# make seed node
|
||||
./makenode.sh 1
|
||||
# establish bootstrap
|
||||
ln -s loki1/self.signed bootstrap.signed
|
@ -0,0 +1,7 @@
|
||||
mkdir loki$1
|
||||
cd loki$1
|
||||
ln -s ../lokinet lokinet$1
|
||||
cp ../lokinet.ini .
|
||||
nano lokinet.ini
|
||||
cd ..
|
||||
echo "killall -9 lokinet$1" >> ../stop.sh
|
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
set +x
|
||||
cd loki1
|
||||
nohup ./lokinet1 $PWD/lokinet.ini &
|
||||
# seed node needs some time to write RC to make sure it's not expired on load for the rest
|
||||
sleep 1
|
||||
cd ../loki2
|
||||
nohup ./lokinet2 $PWD/lokinet.ini &
|
||||
cd ../loki3
|
||||
nohup ./lokinet3 $PWD/lokinet.ini &
|
||||
cd ../loki4
|
||||
nohup ./lokinet4 $PWD/lokinet.ini &
|
||||
cd ../loki5
|
||||
nohup ./lokinet5 $PWD/lokinet.ini &
|
||||
cd ..
|
||||
tail -f loki*/nohup.out
|
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
killall -9 lokinet1
|
||||
killall -9 lokinet2
|
||||
killall -9 lokinet3
|
||||
killall -9 lokinet4
|
||||
killall -9 lokinet5
|
||||
killall -9 lokinet6
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,89 @@
|
||||
#ifndef LLARP_CRYPTO_LIBSODIUM_HPP
|
||||
#define LLARP_CRYPTO_LIBSODIUM_HPP
|
||||
|
||||
#include <crypto/crypto.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace sodium
|
||||
{
|
||||
struct CryptoLibSodium final : public Crypto
|
||||
{
|
||||
CryptoLibSodium();
|
||||
|
||||
~CryptoLibSodium()
|
||||
{
|
||||
}
|
||||
|
||||
/// xchacha symmetric cipher
|
||||
bool
|
||||
xchacha20(llarp_buffer_t, const SharedSecret &,
|
||||
const TunnelNonce &) override;
|
||||
|
||||
/// xchacha symmetric cipher (multibuffer)
|
||||
bool
|
||||
xchacha20_alt(llarp_buffer_t, llarp_buffer_t, const SharedSecret &,
|
||||
const byte_t *) override;
|
||||
|
||||
/// path dh creator's side
|
||||
bool
|
||||
dh_client(SharedSecret &, const PubKey &, const SecretKey &,
|
||||
const TunnelNonce &) override;
|
||||
/// path dh relay side
|
||||
bool
|
||||
dh_server(SharedSecret &, const PubKey &, const SecretKey &,
|
||||
const TunnelNonce &) override;
|
||||
/// transport dh client side
|
||||
bool
|
||||
transport_dh_client(SharedSecret &, const PubKey &, const SecretKey &,
|
||||
const TunnelNonce &) override;
|
||||
/// transport dh server side
|
||||
bool
|
||||
transport_dh_server(SharedSecret &, const PubKey &, const SecretKey &,
|
||||
const TunnelNonce &) override;
|
||||
/// blake2b 512 bit
|
||||
bool
|
||||
hash(byte_t *, llarp_buffer_t) override;
|
||||
/// blake2b 256 bit
|
||||
bool
|
||||
shorthash(ShortHash &, llarp_buffer_t) override;
|
||||
/// blake2s 256 bit hmac
|
||||
bool
|
||||
hmac(byte_t *, llarp_buffer_t, const SharedSecret &) override;
|
||||
/// ed25519 sign
|
||||
bool
|
||||
sign(Signature &, const SecretKey &, llarp_buffer_t) override;
|
||||
/// ed25519 verify
|
||||
bool
|
||||
verify(const PubKey &, llarp_buffer_t, const Signature &) override;
|
||||
/// seed to secretkey
|
||||
bool
|
||||
seed_to_secretkey(llarp::SecretKey &,
|
||||
const llarp::IdentitySecret &) override;
|
||||
/// randomize buffer
|
||||
void randomize(llarp_buffer_t) override;
|
||||
/// randomizer memory
|
||||
void
|
||||
randbytes(void *, size_t) override;
|
||||
/// generate signing keypair
|
||||
void
|
||||
identity_keygen(SecretKey &) override;
|
||||
/// generate encryption keypair
|
||||
void
|
||||
encryption_keygen(SecretKey &) override;
|
||||
/// generate post quantum encrytion key
|
||||
void
|
||||
pqe_keygen(PQKeyPair &) override;
|
||||
/// post quantum decrypt (buffer, sharedkey_dst, sec)
|
||||
bool
|
||||
pqe_decrypt(const PQCipherBlock &, SharedSecret &,
|
||||
const byte_t *) override;
|
||||
/// post quantum encrypt (buffer, sharedkey_dst, pub)
|
||||
bool
|
||||
pqe_encrypt(PQCipherBlock &, SharedSecret &, const PQPubKey &) override;
|
||||
};
|
||||
} // namespace sodium
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,32 @@
|
||||
#include <dht/explorenetworkjob.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/findrouter.hpp>
|
||||
#include <router/router.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
void
|
||||
ExploreNetworkJob::Start(const TXOwner &peer)
|
||||
{
|
||||
parent->DHTSendTo(peer.node.as_array(), new FindRouterMessage(peer.txid));
|
||||
}
|
||||
|
||||
void
|
||||
ExploreNetworkJob::SendReply()
|
||||
{
|
||||
llarp::LogInfo("got ", valuesFound.size(), " routers from exploration");
|
||||
|
||||
auto router = parent->GetRouter();
|
||||
using std::placeholders::_1;
|
||||
for(const auto &pk : valuesFound)
|
||||
{
|
||||
// lookup router
|
||||
parent->LookupRouter(
|
||||
pk, std::bind(&Router::HandleDHTLookupForExplore, router, pk, _1));
|
||||
}
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,45 @@
|
||||
#ifndef LLARP_DHT_EXPLORENETWORKJOB
|
||||
#define LLARP_DHT_EXPLORENETWORKJOB
|
||||
|
||||
#include <dht/tx.hpp>
|
||||
#include <router_id.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct ExploreNetworkJob : public TX< RouterID, RouterID >
|
||||
{
|
||||
ExploreNetworkJob(const RouterID &peer, AbstractContext *ctx)
|
||||
: TX< RouterID, RouterID >(TXOwner{}, peer, ctx)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Validate(const RouterID &) const override
|
||||
{
|
||||
// TODO: check with lokid
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Start(const TXOwner &peer) override;
|
||||
|
||||
bool
|
||||
GetNextPeer(Key_t &, const std::set< Key_t > &) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DoNextRequest(const Key_t &) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,46 @@
|
||||
#include <dht/localrouterlookup.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/gotrouter.hpp>
|
||||
#include <messages/dht.hpp>
|
||||
#include <router/router.hpp>
|
||||
#include <util/logger.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
LocalRouterLookup::LocalRouterLookup(const PathID_t &path, uint64_t txid,
|
||||
const RouterID &target, AbstractContext *ctx)
|
||||
: RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, target, ctx,
|
||||
nullptr)
|
||||
, localPath(path)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LocalRouterLookup::SendReply()
|
||||
{
|
||||
auto path = parent->GetRouter()->paths.GetByUpstream(
|
||||
parent->OurKey().as_array(), localPath);
|
||||
if(!path)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"did not send reply for relayed dht request, no such local path "
|
||||
"for pathid=",
|
||||
localPath);
|
||||
return;
|
||||
}
|
||||
routing::DHTMessage msg;
|
||||
msg.M.emplace_back(new GotRouterMessage(parent->OurKey(), whoasked.txid,
|
||||
valuesFound, true));
|
||||
if(!path->SendRoutingMessage(&msg, parent->GetRouter()))
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"failed to send routing message when informing result of dht "
|
||||
"request, pathid=",
|
||||
localPath);
|
||||
}
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,27 @@
|
||||
#ifndef LLARP_DHT_LOCALROUTERLOOKUP
|
||||
#define LLARP_DHT_LOCALROUTERLOOKUP
|
||||
|
||||
#include <dht/recursiverouterlookup.hpp>
|
||||
|
||||
#include <path/path_types.hpp>
|
||||
#include <router_contact.hpp>
|
||||
#include <router_id.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct LocalRouterLookup : public RecursiveRouterLookup
|
||||
{
|
||||
PathID_t localPath;
|
||||
|
||||
LocalRouterLookup(const PathID_t &path, uint64_t txid,
|
||||
const RouterID &target, AbstractContext *ctx);
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,45 @@
|
||||
#include <dht/localserviceaddresslookup.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/gotintro.hpp>
|
||||
#include <router/router.hpp>
|
||||
#include <util/logger.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
LocalServiceAddressLookup::LocalServiceAddressLookup(
|
||||
const PathID_t &pathid, uint64_t txid, const service::Address &addr,
|
||||
AbstractContext *ctx, __attribute__((unused)) const Key_t &askpeer)
|
||||
: ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, 5,
|
||||
nullptr)
|
||||
, localPath(pathid)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LocalServiceAddressLookup::SendReply()
|
||||
{
|
||||
auto path = parent->GetRouter()->paths.GetByUpstream(
|
||||
parent->OurKey().as_array(), localPath);
|
||||
if(!path)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"did not send reply for relayed dht request, no such local path "
|
||||
"for pathid=",
|
||||
localPath);
|
||||
return;
|
||||
}
|
||||
routing::DHTMessage msg;
|
||||
msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid));
|
||||
if(!path->SendRoutingMessage(&msg, parent->GetRouter()))
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"failed to send routing message when informing result of dht "
|
||||
"request, pathid=",
|
||||
localPath);
|
||||
}
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,27 @@
|
||||
#ifndef LLARP_DHT_LOCALSERVICEADDRESSLOOKUP
|
||||
#define LLARP_DHT_LOCALSERVICEADDRESSLOOKUP
|
||||
|
||||
#include <dht/serviceaddresslookup.hpp>
|
||||
|
||||
#include <path/path_types.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct LocalServiceAddressLookup : public ServiceAddressLookup
|
||||
{
|
||||
PathID_t localPath;
|
||||
|
||||
LocalServiceAddressLookup(const PathID_t &pathid, uint64_t txid,
|
||||
const service::Address &addr, AbstractContext *ctx,
|
||||
__attribute__((unused)) const Key_t &askpeer);
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,43 @@
|
||||
#include <dht/localtaglookup.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/gotintro.hpp>
|
||||
#include <messages/dht.hpp>
|
||||
#include <router/router.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
LocalTagLookup::LocalTagLookup(const PathID_t &path, uint64_t txid,
|
||||
const service::Tag &target, AbstractContext *ctx)
|
||||
: TagLookup(TXOwner{ctx->OurKey(), txid}, target, ctx, 0)
|
||||
, localPath(path)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LocalTagLookup::SendReply()
|
||||
{
|
||||
auto path = parent->GetRouter()->paths.GetByUpstream(
|
||||
parent->OurKey().as_array(), localPath);
|
||||
if(!path)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"did not send reply for relayed dht request, no such local path "
|
||||
"for pathid=",
|
||||
localPath);
|
||||
return;
|
||||
}
|
||||
routing::DHTMessage msg;
|
||||
msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid));
|
||||
if(!path->SendRoutingMessage(&msg, parent->GetRouter()))
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"failed to send routing message when informing result of dht "
|
||||
"request, pathid=",
|
||||
localPath);
|
||||
}
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,23 @@
|
||||
#ifndef LLARP_DHT_LOOKUPTAGLOOKUP
|
||||
#define LLARP_DHT_LOOKUPTAGLOOKUP
|
||||
|
||||
#include <dht/taglookup.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct LocalTagLookup : public TagLookup
|
||||
{
|
||||
PathID_t localPath;
|
||||
|
||||
LocalTagLookup(const PathID_t &path, uint64_t txid,
|
||||
const service::Tag &target, AbstractContext *ctx);
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,46 @@
|
||||
#include <dht/publishservicejob.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/pubintro.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
PublishServiceJob::PublishServiceJob(const TXOwner &asker,
|
||||
const service::IntroSet &introset,
|
||||
AbstractContext *ctx, uint64_t s,
|
||||
const std::set< Key_t > &exclude)
|
||||
: TX< service::Address, service::IntroSet >(asker, introset.A.Addr(),
|
||||
ctx)
|
||||
, S(s)
|
||||
, dontTell(exclude)
|
||||
, I(introset)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PublishServiceJob::Validate(const service::IntroSet &introset) const
|
||||
{
|
||||
if(I.A != introset.A)
|
||||
{
|
||||
llarp::LogWarn(
|
||||
"publish introset acknowledgement acked a different service");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PublishServiceJob::Start(const TXOwner &peer)
|
||||
{
|
||||
std::vector< Key_t > exclude;
|
||||
for(const auto &router : dontTell)
|
||||
{
|
||||
exclude.push_back(router);
|
||||
}
|
||||
parent->DHTSendTo(peer.node.as_array(),
|
||||
new PublishIntroMessage(I, peer.txid, S, exclude));
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,51 @@
|
||||
#ifndef LLARP_DHT_PUBLISHSERVICEJOB
|
||||
#define LLARP_DHT_PUBLISHSERVICEJOB
|
||||
|
||||
#include <dht/tx.hpp>
|
||||
#include <dht/txowner.hpp>
|
||||
#include <service/address.hpp>
|
||||
#include <service/IntroSet.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct PublishServiceJob : public TX< service::Address, service::IntroSet >
|
||||
{
|
||||
uint64_t S;
|
||||
std::set< Key_t > dontTell;
|
||||
service::IntroSet I;
|
||||
|
||||
PublishServiceJob(const TXOwner &asker, const service::IntroSet &introset,
|
||||
AbstractContext *ctx, uint64_t s,
|
||||
const std::set< Key_t > &exclude);
|
||||
|
||||
bool
|
||||
Validate(const service::IntroSet &introset) const override;
|
||||
|
||||
void
|
||||
Start(const TXOwner &peer) override;
|
||||
|
||||
bool
|
||||
GetNextPeer(Key_t &, const std::set< Key_t > &) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DoNextRequest(const Key_t &) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SendReply() override
|
||||
{
|
||||
// don't need this
|
||||
}
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,55 @@
|
||||
#include <dht/recursiverouterlookup.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/findrouter.hpp>
|
||||
#include <dht/messages/gotrouter.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
RecursiveRouterLookup::RecursiveRouterLookup(const TXOwner &whoasked,
|
||||
const RouterID &target,
|
||||
AbstractContext *ctx,
|
||||
RouterLookupHandler result)
|
||||
: TX< RouterID, RouterContact >(whoasked, target, ctx)
|
||||
, resultHandler(result)
|
||||
|
||||
{
|
||||
peersAsked.insert(ctx->OurKey());
|
||||
}
|
||||
|
||||
bool
|
||||
RecursiveRouterLookup::Validate(const RouterContact &rc) const
|
||||
{
|
||||
if(!rc.Verify(parent->Crypto(), parent->Now()))
|
||||
{
|
||||
llarp::LogWarn("rc from lookup result is invalid");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveRouterLookup::Start(const TXOwner &peer)
|
||||
{
|
||||
parent->DHTSendTo(peer.node.as_array(),
|
||||
new FindRouterMessage(peer.txid, target));
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveRouterLookup::SendReply()
|
||||
{
|
||||
if(resultHandler)
|
||||
{
|
||||
resultHandler(valuesFound);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->DHTSendTo(
|
||||
whoasked.node.as_array(),
|
||||
new GotRouterMessage({}, whoasked.txid, valuesFound, false));
|
||||
}
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,42 @@
|
||||
#ifndef LLARP_DHT_RECURSIVEROUTERLOOKUP
|
||||
#define LLARP_DHT_RECURSIVEROUTERLOOKUP
|
||||
|
||||
#include <dht/tx.hpp>
|
||||
|
||||
#include <router_contact.hpp>
|
||||
#include <router_id.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct RecursiveRouterLookup : public TX< RouterID, RouterContact >
|
||||
{
|
||||
RouterLookupHandler resultHandler;
|
||||
RecursiveRouterLookup(const TXOwner &whoasked, const RouterID &target,
|
||||
AbstractContext *ctx, RouterLookupHandler result);
|
||||
|
||||
bool
|
||||
Validate(const RouterContact &rc) const override;
|
||||
|
||||
bool
|
||||
GetNextPeer(Key_t &, const std::set< Key_t > &) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DoNextRequest(const Key_t &) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Start(const TXOwner &peer) override;
|
||||
|
||||
virtual void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,79 @@
|
||||
#include <dht/serviceaddresslookup.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/findintro.hpp>
|
||||
#include <dht/messages/gotintro.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
ServiceAddressLookup::ServiceAddressLookup(
|
||||
const TXOwner &asker, const service::Address &addr, AbstractContext *ctx,
|
||||
uint64_t r, service::IntroSetLookupHandler handler)
|
||||
: TX< service::Address, service::IntroSet >(asker, addr, ctx)
|
||||
, handleResult(handler)
|
||||
, R(r)
|
||||
{
|
||||
peersAsked.insert(ctx->OurKey());
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceAddressLookup::Validate(const service::IntroSet &value) const
|
||||
{
|
||||
if(!value.Verify(parent->Crypto(), parent->Now()))
|
||||
{
|
||||
llarp::LogWarn("Got invalid introset from service lookup");
|
||||
return false;
|
||||
}
|
||||
if(value.A.Addr() != target)
|
||||
{
|
||||
llarp::LogWarn("got introset with wrong target from service lookup");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceAddressLookup::GetNextPeer(Key_t &next,
|
||||
const std::set< Key_t > &exclude)
|
||||
{
|
||||
Key_t k = target.ToKey();
|
||||
return parent->Nodes()->FindCloseExcluding(k, next, exclude);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceAddressLookup::Start(const TXOwner &peer)
|
||||
{
|
||||
parent->DHTSendTo(peer.node.as_array(),
|
||||
new FindIntroMessage(peer.txid, target, R));
|
||||
}
|
||||
|
||||
void
|
||||
ServiceAddressLookup::DoNextRequest(const Key_t &ask)
|
||||
{
|
||||
if(R)
|
||||
{
|
||||
parent->LookupIntroSetRecursive(target, whoasked.node, whoasked.txid,
|
||||
ask, R - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->LookupIntroSetIterative(target, whoasked.node, whoasked.txid,
|
||||
ask);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceAddressLookup::SendReply()
|
||||
{
|
||||
if(handleResult)
|
||||
{
|
||||
handleResult(valuesFound);
|
||||
}
|
||||
|
||||
parent->DHTSendTo(whoasked.node.as_array(),
|
||||
new GotIntroMessage(valuesFound, whoasked.txid));
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,44 @@
|
||||
#ifndef LLARP_DHT_SERVICEADDRESSLOOKUP
|
||||
#define LLARP_DHT_SERVICEADDRESSLOOKUP
|
||||
|
||||
#include <dht/key.hpp>
|
||||
#include <dht/tx.hpp>
|
||||
#include <service/address.hpp>
|
||||
#include <service/IntroSet.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct TXOwner;
|
||||
|
||||
struct ServiceAddressLookup
|
||||
: public TX< service::Address, service::IntroSet >
|
||||
{
|
||||
service::IntroSetLookupHandler handleResult;
|
||||
uint64_t R;
|
||||
|
||||
ServiceAddressLookup(const TXOwner &asker, const service::Address &addr,
|
||||
AbstractContext *ctx, uint64_t r,
|
||||
service::IntroSetLookupHandler handler);
|
||||
|
||||
bool
|
||||
Validate(const service::IntroSet &value) const override;
|
||||
|
||||
bool
|
||||
GetNextPeer(Key_t &next, const std::set< Key_t > &exclude) override;
|
||||
|
||||
void
|
||||
Start(const TXOwner &peer) override;
|
||||
|
||||
void
|
||||
DoNextRequest(const Key_t &ask) override;
|
||||
|
||||
virtual void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,59 @@
|
||||
#include <dht/taglookup.hpp>
|
||||
|
||||
#include <dht/context.hpp>
|
||||
#include <dht/messages/gotintro.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
bool
|
||||
TagLookup::Validate(const service::IntroSet &introset) const
|
||||
{
|
||||
if(!introset.Verify(parent->Crypto(), parent->Now()))
|
||||
{
|
||||
llarp::LogWarn("got invalid introset from tag lookup");
|
||||
return false;
|
||||
}
|
||||
if(introset.topic != target)
|
||||
{
|
||||
llarp::LogWarn("got introset with missmatched topic in tag lookup");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TagLookup::Start(const TXOwner &peer)
|
||||
{
|
||||
parent->DHTSendTo(peer.node.as_array(),
|
||||
new FindIntroMessage(target, peer.txid, R));
|
||||
}
|
||||
|
||||
void
|
||||
TagLookup::SendReply()
|
||||
{
|
||||
std::set< service::IntroSet > found;
|
||||
for(const auto &remoteTag : valuesFound)
|
||||
{
|
||||
found.insert(remoteTag);
|
||||
}
|
||||
// collect our local values if we haven't hit a limit
|
||||
if(found.size() < 2)
|
||||
{
|
||||
for(const auto &localTag :
|
||||
parent->FindRandomIntroSetsWithTagExcluding(target, 1, found))
|
||||
{
|
||||
found.insert(localTag);
|
||||
}
|
||||
}
|
||||
std::vector< service::IntroSet > values;
|
||||
for(const auto &introset : found)
|
||||
{
|
||||
values.push_back(introset);
|
||||
}
|
||||
parent->DHTSendTo(whoasked.node.as_array(),
|
||||
new GotIntroMessage(values, whoasked.txid));
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
@ -0,0 +1,44 @@
|
||||
#ifndef LLARP_DHT_TAGLOOKUP
|
||||
#define LLARP_DHT_TAGLOOKUP
|
||||
|
||||
#include <dht/tx.hpp>
|
||||
#include <service/IntroSet.hpp>
|
||||
#include <service/tag.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct TagLookup : public TX< service::Tag, service::IntroSet >
|
||||
{
|
||||
uint64_t R;
|
||||
TagLookup(const TXOwner &asker, const service::Tag &tag, AbstractContext *ctx,
|
||||
uint64_t r)
|
||||
: TX< service::Tag, service::IntroSet >(asker, tag, ctx), R(r)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Validate(const service::IntroSet &introset) const override;
|
||||
|
||||
void
|
||||
Start(const TXOwner &peer) override;
|
||||
|
||||
bool
|
||||
GetNextPeer(Key_t &, const std::set< Key_t > &) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DoNextRequest(const Key_t &) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SendReply() override;
|
||||
};
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
#include <dht/tx.hpp>
|
@ -0,0 +1,104 @@
|
||||
#ifndef LLARP_DHT_TX
|
||||
#define LLARP_DHT_TX
|
||||
|
||||
#include <dht/key.hpp>
|
||||
#include <dht/txowner.hpp>
|
||||
#include <util/logger.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
struct AbstractContext;
|
||||
|
||||
template < typename K, typename V >
|
||||
struct TX
|
||||
{
|
||||
K target;
|
||||
AbstractContext* parent;
|
||||
std::set< Key_t > peersAsked;
|
||||
std::vector< V > valuesFound;
|
||||
TXOwner whoasked;
|
||||
|
||||
TX(const TXOwner& asker, const K& k, AbstractContext* p)
|
||||
: target(k), parent(p), whoasked(asker)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~TX(){};
|
||||
|
||||
void
|
||||
OnFound(const Key_t& askedPeer, const V& value);
|
||||
|
||||
/// return true if we want to persist this tx
|
||||
bool
|
||||
AskNextPeer(const Key_t& prevPeer, const std::unique_ptr< Key_t >& next);
|
||||
|
||||
virtual bool
|
||||
Validate(const V& value) const = 0;
|
||||
|
||||
virtual void
|
||||
Start(const TXOwner& peer) = 0;
|
||||
|
||||
virtual bool
|
||||
GetNextPeer(Key_t& next, const std::set< Key_t >& exclude) = 0;
|
||||
|
||||
virtual void
|
||||
DoNextRequest(const Key_t& peer) = 0;
|
||||
|
||||
virtual void
|
||||
SendReply() = 0;
|
||||
};
|
||||
|
||||
template < typename K, typename V >
|
||||
inline void
|
||||
TX< K, V >::OnFound(const Key_t& askedPeer, const V& value)
|
||||
{
|
||||
peersAsked.insert(askedPeer);
|
||||
if(Validate(value))
|
||||
{
|
||||
valuesFound.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename K, typename V >
|
||||
inline bool
|
||||
TX< K, V >::AskNextPeer(const Key_t& prevPeer,
|
||||
const std::unique_ptr< Key_t >& next)
|
||||
{
|
||||
peersAsked.insert(prevPeer);
|
||||
Key_t peer;
|
||||
if(next)
|
||||
{
|
||||
// explicit next peer provided
|
||||
peer = *next;
|
||||
}
|
||||
else if(!GetNextPeer(peer, peersAsked))
|
||||
{
|
||||
// no more peers
|
||||
llarp::LogInfo("no more peers for request asking for ", target);
|
||||
return false;
|
||||
}
|
||||
|
||||
const Key_t targetKey{target};
|
||||
if((prevPeer ^ targetKey) < (peer ^ targetKey))
|
||||
{
|
||||
// next peer is not closer
|
||||
llarp::LogInfo("next peer ", peer, " is not closer to ", target,
|
||||
" than ", prevPeer);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
peersAsked.insert(peer);
|
||||
}
|
||||
DoNextRequest(peer);
|
||||
return true;
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
#include <dht/txholder.hpp>
|
@ -0,0 +1,190 @@
|
||||
#ifndef LLARP_DHT_TXHOLDER
|
||||
#define LLARP_DHT_TXHOLDER
|
||||
|
||||
#include <dht/tx.hpp>
|
||||
#include <dht/txowner.hpp>
|
||||
#include <util/logger.hpp>
|
||||
#include <util/time.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace dht
|
||||
{
|
||||
template < typename K, typename V, typename K_Hash,
|
||||
llarp_time_t requestTimeoutMS = 5000UL >
|
||||
struct TXHolder
|
||||
{
|
||||
using TXPtr = std::unique_ptr< TX< K, V > >;
|
||||
// tx who are waiting for a reply for each key
|
||||
std::unordered_multimap< K, TXOwner, K_Hash > waiting;
|
||||
// tx timesouts by key
|
||||
std::unordered_map< K, llarp_time_t, K_Hash > timeouts;
|
||||
// maps remote peer with tx to handle reply from them
|
||||
std::unordered_map< TXOwner, TXPtr, TXOwner::Hash > tx;
|
||||
|
||||
const TX< K, V >*
|
||||
GetPendingLookupFrom(const TXOwner& owner) const;
|
||||
|
||||
bool
|
||||
HasLookupFor(const K& target) const
|
||||
{
|
||||
return timeouts.find(target) != timeouts.end();
|
||||
}
|
||||
|
||||
bool
|
||||
HasPendingLookupFrom(const TXOwner& owner) const
|
||||
{
|
||||
return GetPendingLookupFrom(owner) != nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
NewTX(const TXOwner& askpeer, const TXOwner& whoasked, const K& k,
|
||||
TX< K, V >* t);
|
||||
|
||||
/// mark tx as not fond
|
||||
void
|
||||
NotFound(const TXOwner& from, const std::unique_ptr< Key_t >& next);
|
||||
|
||||
void
|
||||
Found(const TXOwner& from, const K& k, const std::vector< V >& values)
|
||||
{
|
||||
Inform(from, k, values, true);
|
||||
}
|
||||
|
||||
/// inform all watches for key of values found
|
||||
void
|
||||
Inform(TXOwner from, K key, std::vector< V > values,
|
||||
bool sendreply = false, bool removeTimeouts = true);
|
||||
|
||||
void
|
||||
Expire(llarp_time_t now);
|
||||
};
|
||||
|
||||
template < typename K, typename V, typename K_Hash,
|
||||
llarp_time_t requestTimeoutMS >
|
||||
const TX< K, V >*
|
||||
TXHolder< K, V, K_Hash, requestTimeoutMS >::GetPendingLookupFrom(
|
||||
const TXOwner& owner) const
|
||||
{
|
||||
auto itr = tx.find(owner);
|
||||
if(itr == tx.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return itr->second.get();
|
||||
}
|
||||
}
|
||||
|
||||
template < typename K, typename V, typename K_Hash,
|
||||
llarp_time_t requestTimeoutMS >
|
||||
void
|
||||
TXHolder< K, V, K_Hash, requestTimeoutMS >::NewTX(const TXOwner& askpeer,
|
||||
const TXOwner& whoasked,
|
||||
const K& k, TX< K, V >* t)
|
||||
{
|
||||
(void)whoasked;
|
||||
tx.emplace(askpeer, std::unique_ptr< TX< K, V > >(t));
|
||||
auto count = waiting.count(k);
|
||||
waiting.emplace(k, askpeer);
|
||||
|
||||
auto itr = timeouts.find(k);
|
||||
if(itr == timeouts.end())
|
||||
{
|
||||
timeouts.emplace(k, time_now_ms() + requestTimeoutMS);
|
||||
}
|
||||
if(count == 0)
|
||||
{
|
||||
t->Start(askpeer);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename K, typename V, typename K_Hash,
|
||||
llarp_time_t requestTimeoutMS >
|
||||
void
|
||||
TXHolder< K, V, K_Hash, requestTimeoutMS >::NotFound(
|
||||
const TXOwner& from, const std::unique_ptr< Key_t >& next)
|
||||
{
|
||||
bool sendReply = true;
|
||||
auto txitr = tx.find(from);
|
||||
if(txitr == tx.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// ask for next peer
|
||||
if(txitr->second->AskNextPeer(from.node, next))
|
||||
{
|
||||
sendReply = false;
|
||||
}
|
||||
|
||||
llarp::LogWarn("Target key ", txitr->second->target);
|
||||
Inform(from, txitr->second->target, {}, sendReply, sendReply);
|
||||
}
|
||||
|
||||
template < typename K, typename V, typename K_Hash,
|
||||
llarp_time_t requestTimeoutMS >
|
||||
void
|
||||
TXHolder< K, V, K_Hash, requestTimeoutMS >::Inform(TXOwner from, K key,
|
||||
std::vector< V > values,
|
||||
bool sendreply,
|
||||
bool removeTimeouts)
|
||||
{
|
||||
auto range = waiting.equal_range(key);
|
||||
auto itr = range.first;
|
||||
while(itr != range.second)
|
||||
{
|
||||
auto txitr = tx.find(itr->second);
|
||||
if(txitr != tx.end())
|
||||
{
|
||||
for(const auto& value : values)
|
||||
{
|
||||
txitr->second->OnFound(from.node, value);
|
||||
}
|
||||
if(sendreply)
|
||||
{
|
||||
txitr->second->SendReply();
|
||||
tx.erase(txitr);
|
||||
}
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
|
||||
if(sendreply)
|
||||
{
|
||||
waiting.erase(key);
|
||||
}
|
||||
|
||||
if(removeTimeouts)
|
||||
{
|
||||
timeouts.erase(key);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename K, typename V, typename K_Hash,
|
||||
llarp_time_t requestTimeoutMS >
|
||||
void
|
||||
TXHolder< K, V, K_Hash, requestTimeoutMS >::Expire(llarp_time_t now)
|
||||
{
|
||||
auto itr = timeouts.begin();
|
||||
while(itr != timeouts.end())
|
||||
{
|
||||
if(now > itr->second && now - itr->second >= requestTimeoutMS)
|
||||
{
|
||||
Inform(TXOwner{}, itr->first, {}, true, false);
|
||||
itr = timeouts.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
#include <dht/mock_context.hpp>
|
@ -0,0 +1,46 @@
|
||||
#ifndef TEST_LLARP_MOCK_CONTEXT
|
||||
#define TEST_LLARP_MOCK_CONTEXT
|
||||
|
||||
#include <dht/context.hpp>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace test
|
||||
{
|
||||
struct MockContext final : public dht::AbstractContext
|
||||
{
|
||||
MOCK_METHOD2(LookupRouter, bool(const RouterID&, RouterLookupHandler));
|
||||
|
||||
MOCK_METHOD6(LookupIntroSetRecursive,
|
||||
void(const service::Address&, const dht::Key_t&, uint64_t,
|
||||
const dht::Key_t&, uint64_t,
|
||||
service::IntroSetLookupHandler));
|
||||
|
||||
MOCK_METHOD5(LookupIntroSetIterative,
|
||||
void(const service::Address&, const dht::Key_t&, uint64_t,
|
||||
const dht::Key_t&, service::IntroSetLookupHandler));
|
||||
|
||||
MOCK_METHOD3(
|
||||
FindRandomIntroSetsWithTagExcluding,
|
||||
std::set< service::IntroSet >(const service::Tag&, size_t,
|
||||
const std::set< service::IntroSet >&));
|
||||
|
||||
MOCK_METHOD3(DHTSendTo, void(const RouterID&, dht::IMessage*, bool));
|
||||
|
||||
MOCK_CONST_METHOD0(Now, llarp_time_t());
|
||||
|
||||
MOCK_CONST_METHOD0(Crypto, llarp::Crypto*());
|
||||
|
||||
MOCK_CONST_METHOD0(GetRouter, llarp::Router*());
|
||||
|
||||
MOCK_CONST_METHOD0(OurKey, const dht::Key_t&());
|
||||
|
||||
MOCK_CONST_METHOD0(Nodes, dht::Bucket< dht::RCNode >*());
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,105 @@
|
||||
#include <dht/explorenetworkjob.hpp>
|
||||
|
||||
#include <dht/messages/findrouter.hpp>
|
||||
#include <dht/mock_context.hpp>
|
||||
#include <test_util.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace llarp;
|
||||
using namespace ::testing;
|
||||
|
||||
using test::makeBuf;
|
||||
|
||||
struct TestDhtExploreNetworkJob : public ::testing::Test
|
||||
{
|
||||
RouterID peer;
|
||||
test::MockContext context;
|
||||
dht::ExploreNetworkJob exploreNetworkJob;
|
||||
|
||||
TestDhtExploreNetworkJob()
|
||||
: peer(makeBuf< RouterID >(0x01)), exploreNetworkJob(peer, &context)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, validate)
|
||||
{
|
||||
const RouterID other = makeBuf< RouterID >(0x02);
|
||||
ASSERT_TRUE(exploreNetworkJob.Validate(other));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, get_next_peer)
|
||||
{
|
||||
dht::Key_t key = makeBuf< dht::Key_t >(0x02);
|
||||
std::set< dht::Key_t > exclude;
|
||||
ASSERT_FALSE(exploreNetworkJob.GetNextPeer(key, exclude));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, do_next)
|
||||
{
|
||||
const dht::Key_t key = makeBuf< dht::Key_t >(0x02);
|
||||
ASSERT_NO_THROW(exploreNetworkJob.DoNextRequest(key));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, start)
|
||||
{
|
||||
// Verify input arguments are passed correctly.
|
||||
// The actual logic is inside the `dht::AbstractContext` implementation.
|
||||
|
||||
const auto txKey = makeBuf< dht::Key_t >(0x02);
|
||||
uint64_t txId = 4;
|
||||
|
||||
dht::TXOwner txOwner(txKey, txId);
|
||||
|
||||
// clang-format off
|
||||
EXPECT_CALL(context, DHTSendTo(
|
||||
Eq(txKey.as_array()),
|
||||
WhenDynamicCastTo< dht::FindRouterMessage* >(NotNull()),
|
||||
true)
|
||||
).Times(1);
|
||||
// clang-format off
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.Start(txOwner));
|
||||
}
|
||||
|
||||
TEST_F(TestDhtExploreNetworkJob, send_reply)
|
||||
{
|
||||
// Concerns:
|
||||
// - Empty collection
|
||||
// - Lookup router fails (returns false)
|
||||
// - Number of calls matches collection size
|
||||
|
||||
{
|
||||
exploreNetworkJob.valuesFound.clear();
|
||||
EXPECT_CALL(context, LookupRouter(_, _)).Times(0);
|
||||
EXPECT_CALL(context, GetRouter()).WillOnce(Return(nullptr));
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.SendReply());
|
||||
}
|
||||
|
||||
{
|
||||
exploreNetworkJob.valuesFound.clear();
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x00));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x01));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x02));
|
||||
|
||||
EXPECT_CALL(context, GetRouter()).WillOnce(Return(nullptr));
|
||||
EXPECT_CALL(context, LookupRouter(Ne(makeBuf<RouterID>(0x01)), _)).Times(2).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(context, LookupRouter(Eq(makeBuf<RouterID>(0x01)), _)).WillOnce(Return(false));
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.SendReply());
|
||||
}
|
||||
|
||||
{
|
||||
exploreNetworkJob.valuesFound.clear();
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x00));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x01));
|
||||
exploreNetworkJob.valuesFound.push_back(makeBuf<RouterID>(0x02));
|
||||
|
||||
EXPECT_CALL(context, GetRouter()).WillOnce(Return(nullptr));
|
||||
EXPECT_CALL(context, LookupRouter(_, _)).Times(3).WillRepeatedly(Return(true));
|
||||
|
||||
ASSERT_NO_THROW(exploreNetworkJob.SendReply());
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
#include <dht/tx.hpp>
|
||||
|
||||
#include <test_util.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using namespace llarp;
|
||||
using namespace ::testing;
|
||||
|
||||
using llarp::test::makeBuf;
|
||||
|
||||
// Mock implementation of TX.
|
||||
struct TestTx final : public dht::TX< dht::Key_t, std::string >
|
||||
{
|
||||
TestTx(const dht::TXOwner& asker, const dht::Key_t& k,
|
||||
dht::AbstractContext* p)
|
||||
: dht::TX< dht::Key_t, std::string >(asker, k, p)
|
||||
{
|
||||
}
|
||||
|
||||
MOCK_CONST_METHOD1(Validate, bool(const std::string&));
|
||||
|
||||
MOCK_METHOD1(Start, void(const dht::TXOwner&));
|
||||
|
||||
MOCK_METHOD2(GetNextPeer, bool(dht::Key_t&, const std::set< dht::Key_t >&));
|
||||
|
||||
MOCK_METHOD1(DoNextRequest, void(const dht::Key_t&));
|
||||
|
||||
MOCK_METHOD0(SendReply, void());
|
||||
};
|
||||
|
||||
struct TestDhtTx : public Test
|
||||
{
|
||||
dht::TXOwner asker;
|
||||
dht::Key_t key;
|
||||
TestTx tx;
|
||||
|
||||
TestDhtTx() : tx(asker, key, nullptr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestDhtTx, on_found)
|
||||
{
|
||||
// Concerns
|
||||
// - Validate returns true
|
||||
// - Repeated call on success
|
||||
// - Validate returns false
|
||||
// - Repeated call on failure
|
||||
// - Repeated call on success after failure
|
||||
|
||||
const auto key = makeBuf< dht::Key_t >(0x00);
|
||||
std::string val("good value");
|
||||
|
||||
// Validate returns true
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(val)).WillOnce(Return(true));
|
||||
|
||||
tx.OnFound(key, val);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key));
|
||||
ASSERT_THAT(tx.valuesFound, Contains(val));
|
||||
}
|
||||
|
||||
// Repeated call on success
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(val)).WillOnce(Return(true));
|
||||
tx.OnFound(key, val);
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key));
|
||||
ASSERT_THAT(tx.valuesFound, Contains(val));
|
||||
}
|
||||
|
||||
const auto key1 = makeBuf< dht::Key_t >(0x01);
|
||||
std::string badVal("bad value");
|
||||
|
||||
// Validate returns false
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(badVal)).WillOnce(Return(false));
|
||||
|
||||
tx.OnFound(key1, badVal);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key1));
|
||||
ASSERT_THAT(tx.valuesFound, Not(Contains(badVal)));
|
||||
}
|
||||
|
||||
// Repeated call on failure
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(badVal)).WillOnce(Return(false));
|
||||
|
||||
tx.OnFound(key1, badVal);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key1));
|
||||
ASSERT_THAT(tx.valuesFound, Not(Contains(badVal)));
|
||||
}
|
||||
|
||||
// Repeated call on success after failure
|
||||
{
|
||||
EXPECT_CALL(tx, Validate(badVal)).WillOnce(Return(true));
|
||||
|
||||
tx.OnFound(key1, badVal);
|
||||
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key1));
|
||||
ASSERT_THAT(tx.valuesFound, Contains(badVal));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestDhtTx, ask_next_peer)
|
||||
{
|
||||
// Concerns:
|
||||
// - GetNextPeer fails
|
||||
// - Next Peer is not closer
|
||||
// - next ptr is null
|
||||
// - next ptr is not null
|
||||
|
||||
const auto key0 = makeBuf< dht::Key_t >(0x00);
|
||||
const auto key1 = makeBuf< dht::Key_t >(0x01);
|
||||
const auto key2 = makeBuf< dht::Key_t >(0x02);
|
||||
|
||||
{
|
||||
// GetNextPeer fails
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _)).WillOnce(Return(false));
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(0);
|
||||
|
||||
ASSERT_FALSE(tx.AskNextPeer(key0, {}));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key0));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
|
||||
{
|
||||
// Next Peer is not closer
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _))
|
||||
.WillOnce(DoAll(SetArgReferee< 0 >(key1), Return(true)));
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(0);
|
||||
|
||||
ASSERT_FALSE(tx.AskNextPeer(key0, {}));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key0));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
|
||||
{
|
||||
// next ptr is null
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _))
|
||||
.WillOnce(DoAll(SetArgReferee< 0 >(key1), Return(true)));
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(1);
|
||||
|
||||
ASSERT_TRUE(tx.AskNextPeer(key2, {}));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key2));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
|
||||
{
|
||||
// next ptr is not null
|
||||
EXPECT_CALL(tx, GetNextPeer(_, _)).Times(0);
|
||||
|
||||
EXPECT_CALL(tx, DoNextRequest(key1)).Times(1);
|
||||
|
||||
auto ptr = std::make_unique< dht::Key_t >(key1);
|
||||
ASSERT_TRUE(tx.AskNextPeer(key2, ptr));
|
||||
ASSERT_THAT(tx.peersAsked, Contains(key2));
|
||||
|
||||
tx.peersAsked.clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
# Run manually to reformat a file:
|
||||
# clang-format -i --style=file <file>
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
@ -1,2 +1,57 @@
|
||||
# Ignore CI build directory
|
||||
build/
|
||||
xcuserdata
|
||||
cmake-build-debug/
|
||||
.idea/
|
||||
bazel-bin
|
||||
bazel-genfiles
|
||||
bazel-googletest
|
||||
bazel-out
|
||||
bazel-testlogs
|
||||
# python
|
||||
*.pyc
|
||||
|
||||
# Visual Studio files
|
||||
.vs
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.VC.opendb
|
||||
*.suo
|
||||
*.user
|
||||
_ReSharper.Caches/
|
||||
Win32-Debug/
|
||||
Win32-Release/
|
||||
x64-Debug/
|
||||
x64-Release/
|
||||
|
||||
# Ignore autoconf / automake files
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
configure
|
||||
build-aux/
|
||||
autom4te.cache/
|
||||
googletest/m4/libtool.m4
|
||||
googletest/m4/ltoptions.m4
|
||||
googletest/m4/ltsugar.m4
|
||||
googletest/m4/ltversion.m4
|
||||
googletest/m4/lt~obsolete.m4
|
||||
|
||||
# Ignore generated directories.
|
||||
googlemock/fused-src/
|
||||
googletest/fused-src/
|
||||
|
||||
# macOS files
|
||||
.DS_Store
|
||||
googletest/.DS_Store
|
||||
googletest/xcode/.DS_Store
|
||||
|
||||
# Ignore cmake generated directories and files.
|
||||
CMakeFiles
|
||||
CTestTestfile.cmake
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
googlemock/CMakeFiles
|
||||
googlemock/CTestTestfile.cmake
|
||||
googlemock/Makefile
|
||||
googlemock/cmake_install.cmake
|
||||
googlemock/gtest
|
||||
|
@ -0,0 +1,78 @@
|
||||
# Build matrix / environment variable are explained on:
|
||||
# https://docs.travis-ci.com/user/customizing-the-build/
|
||||
# This file can be validated on:
|
||||
# http://lint.travis-ci.org/
|
||||
|
||||
sudo: false
|
||||
language: cpp
|
||||
|
||||
# Define the matrix explicitly, manually expanding the combinations of (os, compiler, env).
|
||||
# It is more tedious, but grants us far more flexibility.
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
group: deprecated-2017Q3
|
||||
before_install: chmod -R +x ./ci/*platformio.sh
|
||||
install: ./ci/install-platformio.sh
|
||||
script: ./ci/build-platformio.sh
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
sudo : true
|
||||
install: ./ci/install-linux.sh && ./ci/log-config.sh
|
||||
script: ./ci/build-linux-bazel.sh
|
||||
- os: linux
|
||||
compiler: clang
|
||||
sudo : true
|
||||
install: ./ci/install-linux.sh && ./ci/log-config.sh
|
||||
script: ./ci/build-linux-bazel.sh
|
||||
- os: linux
|
||||
group: deprecated-2017Q4
|
||||
compiler: gcc
|
||||
install: ./ci/install-linux.sh && ./ci/log-config.sh
|
||||
script: ./ci/build-linux-autotools.sh
|
||||
env: VERBOSE=1 CXXFLAGS=-std=c++11
|
||||
- os: linux
|
||||
group: deprecated-2017Q4
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Debug VERBOSE=1 CXX_FLAGS=-std=c++11
|
||||
- os: linux
|
||||
group: deprecated-2017Q4
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 NO_EXCEPTION=ON NO_RTTI=ON COMPILER_IS_GNUCXX=ON
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
|
||||
- os: osx
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
|
||||
if: type != pull_request
|
||||
|
||||
# These are the install and build (script) phases for the most common entries in the matrix. They could be included
|
||||
# in each entry in the matrix, but that is just repetitive.
|
||||
install:
|
||||
- ./ci/install-${TRAVIS_OS_NAME}.sh
|
||||
- . ./ci/env-${TRAVIS_OS_NAME}.sh
|
||||
- ./ci/log-config.sh
|
||||
|
||||
script: ./ci/travis.sh
|
||||
|
||||
# For sudo=false builds this section installs the necessary dependencies.
|
||||
addons:
|
||||
apt:
|
||||
# List of whitelisted in travis packages for ubuntu-precise can be found here:
|
||||
# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
|
||||
# List of whitelisted in travis apt-sources:
|
||||
# https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
packages:
|
||||
- g++-4.9
|
||||
- clang-3.9
|
||||
|
||||
notifications:
|
||||
email: false
|
@ -0,0 +1,166 @@
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Author: misterg@google.com (Gennadiy Civil)
|
||||
#
|
||||
# Bazel Build for Google C++ Testing Framework(Google Test)
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = ["@bazel_tools//platforms:windows"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "has_absl",
|
||||
values = {"define": "absl=1"},
|
||||
)
|
||||
|
||||
# Library that defines the FRIEND_TEST macro.
|
||||
cc_library(
|
||||
name = "gtest_prod",
|
||||
hdrs = ["googletest/include/gtest/gtest_prod.h"],
|
||||
includes = ["googletest/include"],
|
||||
)
|
||||
|
||||
# Google Test including Google Mock
|
||||
cc_library(
|
||||
name = "gtest",
|
||||
srcs = glob(
|
||||
include = [
|
||||
"googletest/src/*.cc",
|
||||
"googletest/src/*.h",
|
||||
"googletest/include/gtest/**/*.h",
|
||||
"googlemock/src/*.cc",
|
||||
"googlemock/include/gmock/**/*.h",
|
||||
],
|
||||
exclude = [
|
||||
"googletest/src/gtest-all.cc",
|
||||
"googletest/src/gtest_main.cc",
|
||||
"googlemock/src/gmock-all.cc",
|
||||
"googlemock/src/gmock_main.cc",
|
||||
],
|
||||
),
|
||||
hdrs = glob([
|
||||
"googletest/include/gtest/*.h",
|
||||
"googlemock/include/gmock/*.h",
|
||||
]),
|
||||
copts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
defines = select({
|
||||
":has_absl": ["GTEST_HAS_ABSL=1"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
includes = [
|
||||
"googlemock",
|
||||
"googlemock/include",
|
||||
"googletest",
|
||||
"googletest/include",
|
||||
],
|
||||
linkopts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
deps = select({
|
||||
":has_absl": [
|
||||
"@com_google_absl//absl/debugging:failure_signal_handler",
|
||||
"@com_google_absl//absl/debugging:stacktrace",
|
||||
"@com_google_absl//absl/debugging:symbolize",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
"@com_google_absl//absl/types:variant",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "gtest_main",
|
||||
srcs = ["googlemock/src/gmock_main.cc"],
|
||||
deps = [":gtest"],
|
||||
)
|
||||
|
||||
# The following rules build samples of how to use gTest.
|
||||
cc_library(
|
||||
name = "gtest_sample_lib",
|
||||
srcs = [
|
||||
"googletest/samples/sample1.cc",
|
||||
"googletest/samples/sample2.cc",
|
||||
"googletest/samples/sample4.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"googletest/samples/prime_tables.h",
|
||||
"googletest/samples/sample1.h",
|
||||
"googletest/samples/sample2.h",
|
||||
"googletest/samples/sample3-inl.h",
|
||||
"googletest/samples/sample4.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "gtest_samples",
|
||||
size = "small",
|
||||
# All Samples except:
|
||||
# sample9 (main)
|
||||
# sample10 (main and takes a command line option and needs to be separate)
|
||||
srcs = [
|
||||
"googletest/samples/sample1_unittest.cc",
|
||||
"googletest/samples/sample2_unittest.cc",
|
||||
"googletest/samples/sample3_unittest.cc",
|
||||
"googletest/samples/sample4_unittest.cc",
|
||||
"googletest/samples/sample5_unittest.cc",
|
||||
"googletest/samples/sample6_unittest.cc",
|
||||
"googletest/samples/sample7_unittest.cc",
|
||||
"googletest/samples/sample8_unittest.cc",
|
||||
],
|
||||
deps = [
|
||||
"gtest_sample_lib",
|
||||
":gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "sample9_unittest",
|
||||
size = "small",
|
||||
srcs = ["googletest/samples/sample9_unittest.cc"],
|
||||
deps = [":gtest"],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "sample10_unittest",
|
||||
size = "small",
|
||||
srcs = ["googletest/samples/sample10_unittest.cc"],
|
||||
deps = [":gtest"],
|
||||
)
|
@ -1,157 +0,0 @@
|
||||
Changes for 1.7.0:
|
||||
|
||||
* New feature: death tests are supported on OpenBSD and in iOS
|
||||
simulator now.
|
||||
* New feature: Google Test now implements a protocol to allow
|
||||
a test runner to detect that a test program has exited
|
||||
prematurely and report it as a failure (before it would be
|
||||
falsely reported as a success if the exit code is 0).
|
||||
* New feature: Test::RecordProperty() can now be used outside of the
|
||||
lifespan of a test method, in which case it will be attributed to
|
||||
the current test case or the test program in the XML report.
|
||||
* New feature (potentially breaking): --gtest_list_tests now prints
|
||||
the type parameters and value parameters for each test.
|
||||
* Improvement: char pointers and char arrays are now escaped properly
|
||||
in failure messages.
|
||||
* Improvement: failure summary in XML reports now includes file and
|
||||
line information.
|
||||
* Improvement: the <testsuites> XML element now has a timestamp attribute.
|
||||
* Improvement: When --gtest_filter is specified, XML report now doesn't
|
||||
contain information about tests that are filtered out.
|
||||
* Fixed the bug where long --gtest_filter flag values are truncated in
|
||||
death tests.
|
||||
* Potentially breaking change: RUN_ALL_TESTS() is now implemented as a
|
||||
function instead of a macro in order to work better with Clang.
|
||||
* Compatibility fixes with C++ 11 and various platforms.
|
||||
* Bug/warning fixes.
|
||||
|
||||
Changes for 1.6.0:
|
||||
|
||||
* New feature: ADD_FAILURE_AT() for reporting a test failure at the
|
||||
given source location -- useful for writing testing utilities.
|
||||
* New feature: the universal value printer is moved from Google Mock
|
||||
to Google Test.
|
||||
* New feature: type parameters and value parameters are reported in
|
||||
the XML report now.
|
||||
* A gtest_disable_pthreads CMake option.
|
||||
* Colored output works in GNU Screen sessions now.
|
||||
* Parameters of value-parameterized tests are now printed in the
|
||||
textual output.
|
||||
* Failures from ad hoc test assertions run before RUN_ALL_TESTS() are
|
||||
now correctly reported.
|
||||
* Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to
|
||||
ostream.
|
||||
* More complete handling of exceptions.
|
||||
* GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter
|
||||
name is already used by another library.
|
||||
* --gtest_catch_exceptions is now true by default, allowing a test
|
||||
program to continue after an exception is thrown.
|
||||
* Value-parameterized test fixtures can now derive from Test and
|
||||
WithParamInterface<T> separately, easing conversion of legacy tests.
|
||||
* Death test messages are clearly marked to make them more
|
||||
distinguishable from other messages.
|
||||
* Compatibility fixes for Android, Google Native Client, MinGW, HP UX,
|
||||
PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear),
|
||||
IBM XL C++ (Visual Age C++), and C++0x.
|
||||
* Bug fixes and implementation clean-ups.
|
||||
* Potentially incompatible changes: disables the harmful 'make install'
|
||||
command in autotools.
|
||||
|
||||
Changes for 1.5.0:
|
||||
|
||||
* New feature: assertions can be safely called in multiple threads
|
||||
where the pthreads library is available.
|
||||
* New feature: predicates used inside EXPECT_TRUE() and friends
|
||||
can now generate custom failure messages.
|
||||
* New feature: Google Test can now be compiled as a DLL.
|
||||
* New feature: fused source files are included.
|
||||
* New feature: prints help when encountering unrecognized Google Test flags.
|
||||
* Experimental feature: CMake build script (requires CMake 2.6.4+).
|
||||
* Experimental feature: the Pump script for meta programming.
|
||||
* double values streamed to an assertion are printed with enough precision
|
||||
to differentiate any two different values.
|
||||
* Google Test now works on Solaris and AIX.
|
||||
* Build and test script improvements.
|
||||
* Bug fixes and implementation clean-ups.
|
||||
|
||||
Potentially breaking changes:
|
||||
|
||||
* Stopped supporting VC++ 7.1 with exceptions disabled.
|
||||
* Dropped support for 'make install'.
|
||||
|
||||
Changes for 1.4.0:
|
||||
|
||||
* New feature: the event listener API
|
||||
* New feature: test shuffling
|
||||
* New feature: the XML report format is closer to junitreport and can
|
||||
be parsed by Hudson now.
|
||||
* New feature: when a test runs under Visual Studio, its failures are
|
||||
integrated in the IDE.
|
||||
* New feature: /MD(d) versions of VC++ projects.
|
||||
* New feature: elapsed time for the tests is printed by default.
|
||||
* New feature: comes with a TR1 tuple implementation such that Boost
|
||||
is no longer needed for Combine().
|
||||
* New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
|
||||
* New feature: the Xcode project can now produce static gtest
|
||||
libraries in addition to a framework.
|
||||
* Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
|
||||
Symbian, gcc, and C++Builder.
|
||||
* Bug fixes and implementation clean-ups.
|
||||
|
||||
Changes for 1.3.0:
|
||||
|
||||
* New feature: death tests on Windows, Cygwin, and Mac.
|
||||
* New feature: ability to use Google Test assertions in other testing
|
||||
frameworks.
|
||||
* New feature: ability to run disabled test via
|
||||
--gtest_also_run_disabled_tests.
|
||||
* New feature: the --help flag for printing the usage.
|
||||
* New feature: access to Google Test flag values in user code.
|
||||
* New feature: a script that packs Google Test into one .h and one
|
||||
.cc file for easy deployment.
|
||||
* New feature: support for distributing test functions to multiple
|
||||
machines (requires support from the test runner).
|
||||
* Bug fixes and implementation clean-ups.
|
||||
|
||||
Changes for 1.2.1:
|
||||
|
||||
* Compatibility fixes for Linux IA-64 and IBM z/OS.
|
||||
* Added support for using Boost and other TR1 implementations.
|
||||
* Changes to the build scripts to support upcoming release of Google C++
|
||||
Mocking Framework.
|
||||
* Added Makefile to the distribution package.
|
||||
* Improved build instructions in README.
|
||||
|
||||
Changes for 1.2.0:
|
||||
|
||||
* New feature: value-parameterized tests.
|
||||
* New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS)
|
||||
macros.
|
||||
* Changed the XML report format to match JUnit/Ant's.
|
||||
* Added tests to the Xcode project.
|
||||
* Added scons/SConscript for building with SCons.
|
||||
* Added src/gtest-all.cc for building Google Test from a single file.
|
||||
* Fixed compatibility with Solaris and z/OS.
|
||||
* Enabled running Python tests on systems with python 2.3 installed,
|
||||
e.g. Mac OS X 10.4.
|
||||
* Bug fixes.
|
||||
|
||||
Changes for 1.1.0:
|
||||
|
||||
* New feature: type-parameterized tests.
|
||||
* New feature: exception assertions.
|
||||
* New feature: printing elapsed time of tests.
|
||||
* Improved the robustness of death tests.
|
||||
* Added an Xcode project and samples.
|
||||
* Adjusted the output format on Windows to be understandable by Visual Studio.
|
||||
* Minor bug fixes.
|
||||
|
||||
Changes for 1.0.1:
|
||||
|
||||
* Added project files for Visual Studio 7.1.
|
||||
* Fixed issues with compiling on Mac OS X.
|
||||
* Fixed issues with compiling on Cygwin.
|
||||
|
||||
Changes for 1.0.0:
|
||||
|
||||
* Initial Open Source release of Google Test
|
@ -1,290 +1,31 @@
|
||||
########################################################################
|
||||
# CMake build script for Google Test.
|
||||
#
|
||||
# To run the tests for Google Test itself on Linux, use 'make test' or
|
||||
# ctest. You can select which tests to run using 'ctest -R regex'.
|
||||
# For more options, run 'ctest --help'.
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
|
||||
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
|
||||
# make it prominent in the GUI.
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
|
||||
|
||||
# When other libraries are using a shared version of runtime libraries,
|
||||
# Google Test also has to use one.
|
||||
option(
|
||||
gtest_force_shared_crt
|
||||
"Use shared (DLL) run-time lib even when Google Test is built as static lib."
|
||||
OFF)
|
||||
|
||||
option(gtest_build_tests "Build all of gtest's own tests." OFF)
|
||||
|
||||
option(gtest_build_samples "Build gtest's sample programs." OFF)
|
||||
|
||||
if (NOT WIN32)
|
||||
option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
add_definitions(-std=c++11)
|
||||
else()
|
||||
option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON)
|
||||
endif(NOT WIN32)
|
||||
|
||||
option(
|
||||
gtest_hide_internal_symbols
|
||||
"Build gtest with internal symbols hidden in shared libraries."
|
||||
OFF)
|
||||
|
||||
# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
|
||||
include(cmake/hermetic_build.cmake OPTIONAL)
|
||||
|
||||
if (COMMAND pre_project_set_up_hermetic_build)
|
||||
pre_project_set_up_hermetic_build()
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Project-wide settings
|
||||
|
||||
# Name of the project.
|
||||
#
|
||||
# CMake files in this project can refer to the root source directory
|
||||
# as ${gtest_SOURCE_DIR} and to the root binary directory as
|
||||
# ${gtest_BINARY_DIR}.
|
||||
# Language "C" is required for find_package(Threads).
|
||||
project(gtest CXX C)
|
||||
cmake_minimum_required(VERSION 2.6.2)
|
||||
|
||||
if (COMMAND set_up_hermetic_build)
|
||||
set_up_hermetic_build()
|
||||
endif()
|
||||
|
||||
if (gtest_hide_internal_symbols)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
|
||||
endif()
|
||||
|
||||
# Define helper functions and macros used by Google Test.
|
||||
include(cmake/internal_utils.cmake)
|
||||
|
||||
config_compiler_and_linker() # Defined in internal_utils.cmake.
|
||||
|
||||
# Where Google Test's .h files can be found.
|
||||
include_directories(
|
||||
${gtest_SOURCE_DIR}/include
|
||||
${gtest_SOURCE_DIR})
|
||||
|
||||
# Where Google Test's libraries can be found.
|
||||
link_directories(${gtest_BINARY_DIR}/src)
|
||||
|
||||
# Summary of tuple support for Microsoft Visual Studio:
|
||||
# Compiler version(MS) version(cmake) Support
|
||||
# ---------- ----------- -------------- -----------------------------
|
||||
# <= VS 2010 <= 10 <= 1600 Use Google Tests's own tuple.
|
||||
# VS 2012 11 1700 std::tr1::tuple + _VARIADIC_MAX=10
|
||||
# VS 2013 12 1800 std::tr1::tuple
|
||||
if (MSVC AND MSVC_VERSION EQUAL 1700)
|
||||
add_definitions(/D _VARIADIC_MAX=10)
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Defines the gtest & gtest_main libraries. User tests should link
|
||||
# with one of them.
|
||||
|
||||
# Google Test libraries. We build them using more strict warnings than what
|
||||
# are used for other targets, to ensure that gtest can be compiled by a user
|
||||
# aggressive about warnings.
|
||||
cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
|
||||
cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
|
||||
target_link_libraries(gtest_main gtest)
|
||||
|
||||
# If the CMake version supports it, attach header directory information
|
||||
# to the targets for when we are part of a parent build (ie being pulled
|
||||
# in via add_subdirectory() rather than being a standalone build).
|
||||
if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
|
||||
target_include_directories(gtest INTERFACE "${gtest_SOURCE_DIR}/include")
|
||||
target_include_directories(gtest_main INTERFACE "${gtest_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Install rules
|
||||
#install(TARGETS gtest gtest_main
|
||||
# DESTINATION lib)
|
||||
#install(DIRECTORY ${gtest_SOURCE_DIR}/include/gtest
|
||||
# DESTINATION include)
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Samples on how to link user tests with gtest or gtest_main.
|
||||
#
|
||||
# They are not built by default. To build them, set the
|
||||
# gtest_build_samples option to ON. You can do it by running ccmake
|
||||
# or specifying the -Dgtest_build_samples=ON flag when running cmake.
|
||||
|
||||
if (gtest_build_samples)
|
||||
cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
|
||||
cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
|
||||
cxx_executable(sample3_unittest samples gtest_main)
|
||||
cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
|
||||
cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
|
||||
cxx_executable(sample6_unittest samples gtest_main)
|
||||
cxx_executable(sample7_unittest samples gtest_main)
|
||||
cxx_executable(sample8_unittest samples gtest_main)
|
||||
cxx_executable(sample9_unittest samples gtest)
|
||||
cxx_executable(sample10_unittest samples gtest)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# Google Test's own tests.
|
||||
#
|
||||
# You can skip this section if you aren't interested in testing
|
||||
# Google Test itself.
|
||||
#
|
||||
# The tests are not built by default. To build them, set the
|
||||
# gtest_build_tests option to ON. You can do it by running ccmake
|
||||
# or specifying the -Dgtest_build_tests=ON flag when running cmake.
|
||||
|
||||
if (gtest_build_tests)
|
||||
# This must be set in the root directory for the tests to be run by
|
||||
# 'make test' or ctest.
|
||||
enable_testing()
|
||||
|
||||
############################################################
|
||||
# C++ tests built with standard compiler flags.
|
||||
|
||||
cxx_test(gtest-death-test_test gtest_main)
|
||||
cxx_test(gtest_environment_test gtest)
|
||||
cxx_test(gtest-filepath_test gtest_main)
|
||||
cxx_test(gtest-linked_ptr_test gtest_main)
|
||||
cxx_test(gtest-listener_test gtest_main)
|
||||
cxx_test(gtest_main_unittest gtest_main)
|
||||
cxx_test(gtest-message_test gtest_main)
|
||||
cxx_test(gtest_no_test_unittest gtest)
|
||||
cxx_test(gtest-options_test gtest_main)
|
||||
cxx_test(gtest-param-test_test gtest
|
||||
test/gtest-param-test2_test.cc)
|
||||
cxx_test(gtest-port_test gtest_main)
|
||||
cxx_test(gtest_pred_impl_unittest gtest_main)
|
||||
cxx_test(gtest_premature_exit_test gtest
|
||||
test/gtest_premature_exit_test.cc)
|
||||
cxx_test(gtest-printers_test gtest_main)
|
||||
cxx_test(gtest_prod_test gtest_main
|
||||
test/production.cc)
|
||||
cxx_test(gtest_repeat_test gtest)
|
||||
cxx_test(gtest_sole_header_test gtest_main)
|
||||
cxx_test(gtest_stress_test gtest)
|
||||
cxx_test(gtest-test-part_test gtest_main)
|
||||
cxx_test(gtest_throw_on_failure_ex_test gtest)
|
||||
cxx_test(gtest-typed-test_test gtest_main
|
||||
test/gtest-typed-test2_test.cc)
|
||||
cxx_test(gtest_unittest gtest_main)
|
||||
cxx_test(gtest-unittest-api_test gtest)
|
||||
|
||||
############################################################
|
||||
# C++ tests built with non-standard compiler flags.
|
||||
|
||||
# MSVC 7.1 does not support STL with exceptions disabled.
|
||||
if (NOT MSVC OR MSVC_VERSION GREATER 1310)
|
||||
cxx_library(gtest_no_exception "${cxx_no_exception}"
|
||||
src/gtest-all.cc)
|
||||
cxx_library(gtest_main_no_exception "${cxx_no_exception}"
|
||||
src/gtest-all.cc src/gtest_main.cc)
|
||||
endif()
|
||||
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
|
||||
src/gtest-all.cc src/gtest_main.cc)
|
||||
|
||||
cxx_test_with_flags(gtest-death-test_ex_nocatch_test
|
||||
"${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
|
||||
gtest test/gtest-death-test_ex_test.cc)
|
||||
cxx_test_with_flags(gtest-death-test_ex_catch_test
|
||||
"${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
|
||||
gtest test/gtest-death-test_ex_test.cc)
|
||||
|
||||
cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
|
||||
gtest_main_no_rtti test/gtest_unittest.cc)
|
||||
|
||||
cxx_shared_library(gtest_dll "${cxx_default}"
|
||||
src/gtest-all.cc src/gtest_main.cc)
|
||||
|
||||
cxx_executable_with_flags(gtest_dll_test_ "${cxx_default}"
|
||||
gtest_dll test/gtest_all_test.cc)
|
||||
set_target_properties(gtest_dll_test_
|
||||
PROPERTIES
|
||||
COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
|
||||
|
||||
if (NOT MSVC OR MSVC_VERSION LESS 1600) # 1600 is Visual Studio 2010.
|
||||
# Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that
|
||||
# conflict with our own definitions. Therefore using our own tuple does not
|
||||
# work on those compilers.
|
||||
cxx_library(gtest_main_use_own_tuple "${cxx_use_own_tuple}"
|
||||
src/gtest-all.cc src/gtest_main.cc)
|
||||
|
||||
cxx_test_with_flags(gtest-tuple_test "${cxx_use_own_tuple}"
|
||||
gtest_main_use_own_tuple test/gtest-tuple_test.cc)
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
cxx_test_with_flags(gtest_use_own_tuple_test "${cxx_use_own_tuple}"
|
||||
gtest_main_use_own_tuple
|
||||
test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
|
||||
endif()
|
||||
project(googletest-distribution)
|
||||
set(GOOGLETEST_VERSION 1.9.0)
|
||||
|
||||
############################################################
|
||||
# Python tests.
|
||||
enable_testing()
|
||||
|
||||
cxx_executable(gtest_break_on_failure_unittest_ test gtest)
|
||||
py_test(gtest_break_on_failure_unittest)
|
||||
include(CMakeDependentOption)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Visual Studio .NET 2003 does not support STL with exceptions disabled.
|
||||
if (NOT MSVC OR MSVC_VERSION GREATER 1310) # 1310 is Visual Studio .NET 2003
|
||||
cxx_executable_with_flags(
|
||||
gtest_catch_exceptions_no_ex_test_
|
||||
"${cxx_no_exception}"
|
||||
gtest_main_no_exception
|
||||
test/gtest_catch_exceptions_test_.cc)
|
||||
endif()
|
||||
#Note that googlemock target already builds googletest
|
||||
option(BUILD_GMOCK "Builds the googlemock subproject" ON)
|
||||
option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
|
||||
|
||||
cxx_executable_with_flags(
|
||||
gtest_catch_exceptions_ex_test_
|
||||
"${cxx_exception}"
|
||||
gtest_main
|
||||
test/gtest_catch_exceptions_test_.cc)
|
||||
py_test(gtest_catch_exceptions_test)
|
||||
|
||||
cxx_executable(gtest_color_test_ test gtest)
|
||||
py_test(gtest_color_test)
|
||||
|
||||
cxx_executable(gtest_env_var_test_ test gtest)
|
||||
py_test(gtest_env_var_test)
|
||||
|
||||
cxx_executable(gtest_filter_unittest_ test gtest)
|
||||
py_test(gtest_filter_unittest)
|
||||
|
||||
cxx_executable(gtest_help_test_ test gtest_main)
|
||||
py_test(gtest_help_test)
|
||||
|
||||
cxx_executable(gtest_list_tests_unittest_ test gtest)
|
||||
py_test(gtest_list_tests_unittest)
|
||||
|
||||
cxx_executable(gtest_output_test_ test gtest)
|
||||
py_test(gtest_output_test)
|
||||
|
||||
cxx_executable(gtest_shuffle_test_ test gtest)
|
||||
py_test(gtest_shuffle_test)
|
||||
|
||||
# MSVC 7.1 does not support STL with exceptions disabled.
|
||||
if (NOT MSVC OR MSVC_VERSION GREATER 1310)
|
||||
cxx_executable(gtest_throw_on_failure_test_ test gtest_no_exception)
|
||||
set_target_properties(gtest_throw_on_failure_test_
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${cxx_no_exception}")
|
||||
py_test(gtest_throw_on_failure_test)
|
||||
endif()
|
||||
|
||||
cxx_executable(gtest_uninitialized_test_ test gtest)
|
||||
py_test(gtest_uninitialized_test)
|
||||
|
||||
cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
|
||||
cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
|
||||
py_test(gtest_xml_outfiles_test)
|
||||
|
||||
cxx_executable(gtest_xml_output_unittest_ test gtest)
|
||||
py_test(gtest_xml_output_unittest)
|
||||
if(BUILD_GMOCK)
|
||||
add_subdirectory( googlemock )
|
||||
else()
|
||||
add_subdirectory( googletest )
|
||||
endif()
|
||||
|
@ -0,0 +1,161 @@
|
||||
# How to become a contributor and submit your own code
|
||||
|
||||
## Contributor License Agreements
|
||||
|
||||
We'd love to accept your patches! Before we can take them, we
|
||||
have to jump a couple of legal hurdles.
|
||||
|
||||
Please fill out either the individual or corporate Contributor License Agreement
|
||||
(CLA).
|
||||
|
||||
* If you are an individual writing original source code and you're sure you
|
||||
own the intellectual property, then you'll need to sign an
|
||||
[individual CLA](https://developers.google.com/open-source/cla/individual).
|
||||
* If you work for a company that wants to allow you to contribute your work,
|
||||
then you'll need to sign a
|
||||
[corporate CLA](https://developers.google.com/open-source/cla/corporate).
|
||||
|
||||
Follow either of the two links above to access the appropriate CLA and
|
||||
instructions for how to sign and return it. Once we receive it, we'll be able to
|
||||
accept your pull requests.
|
||||
|
||||
## Are you a Googler?
|
||||
If you are a Googler, you can either create an internal change or work on GitHub directly.
|
||||
|
||||
|
||||
## Contributing A Patch
|
||||
|
||||
1. Submit an issue describing your proposed change to the
|
||||
[issue tracker](https://github.com/google/googletest).
|
||||
1. Please don't mix more than one logical change per submittal,
|
||||
because it makes the history hard to follow. If you want to make a
|
||||
change that doesn't have a corresponding issue in the issue
|
||||
tracker, please create one.
|
||||
1. Also, coordinate with team members that are listed on the issue in
|
||||
question. This ensures that work isn't being duplicated and
|
||||
communicating your plan early also generally leads to better
|
||||
patches.
|
||||
1. If your proposed change is accepted, and you haven't already done so, sign a
|
||||
Contributor License Agreement (see details above).
|
||||
1. Fork the desired repo, develop and test your code changes.
|
||||
1. Ensure that your code adheres to the existing style in the sample to which
|
||||
you are contributing.
|
||||
1. Ensure that your code has an appropriate set of unit tests which all pass.
|
||||
1. Submit a pull request.
|
||||
|
||||
## The Google Test and Google Mock Communities ##
|
||||
|
||||
The Google Test community exists primarily through the
|
||||
[discussion group](http://groups.google.com/group/googletestframework)
|
||||
and the GitHub repository.
|
||||
Likewise, the Google Mock community exists primarily through their own
|
||||
[discussion group](http://groups.google.com/group/googlemock).
|
||||
You are definitely encouraged to contribute to the
|
||||
discussion and you can also help us to keep the effectiveness of the
|
||||
group high by following and promoting the guidelines listed here.
|
||||
|
||||
### Please Be Friendly ###
|
||||
|
||||
Showing courtesy and respect to others is a vital part of the Google
|
||||
culture, and we strongly encourage everyone participating in Google
|
||||
Test development to join us in accepting nothing less. Of course,
|
||||
being courteous is not the same as failing to constructively disagree
|
||||
with each other, but it does mean that we should be respectful of each
|
||||
other when enumerating the 42 technical reasons that a particular
|
||||
proposal may not be the best choice. There's never a reason to be
|
||||
antagonistic or dismissive toward anyone who is sincerely trying to
|
||||
contribute to a discussion.
|
||||
|
||||
Sure, C++ testing is serious business and all that, but it's also
|
||||
a lot of fun. Let's keep it that way. Let's strive to be one of the
|
||||
friendliest communities in all of open source.
|
||||
|
||||
As always, discuss Google Test in the official GoogleTest discussion group.
|
||||
You don't have to actually submit code in order to sign up. Your participation
|
||||
itself is a valuable contribution.
|
||||
|
||||
## Style
|
||||
|
||||
To keep the source consistent, readable, diffable and easy to merge,
|
||||
we use a fairly rigid coding style, as defined by the [google-styleguide](https://github.com/google/styleguide) project. All patches will be expected
|
||||
to conform to the style outlined [here](https://google.github.io/styleguide/cppguide.html).
|
||||
Use [.clang-format](https://github.com/google/googletest/blob/master/.clang-format) to check your formatting
|
||||
|
||||
## Requirements for Contributors ###
|
||||
|
||||
If you plan to contribute a patch, you need to build Google Test,
|
||||
Google Mock, and their own tests from a git checkout, which has
|
||||
further requirements:
|
||||
|
||||
* [Python](https://www.python.org/) v2.3 or newer (for running some of
|
||||
the tests and re-generating certain source files from templates)
|
||||
* [CMake](https://cmake.org/) v2.6.4 or newer
|
||||
* [GNU Build System](https://en.wikipedia.org/wiki/GNU_Build_System)
|
||||
including automake (>= 1.9), autoconf (>= 2.59), and
|
||||
libtool / libtoolize.
|
||||
|
||||
## Developing Google Test ##
|
||||
|
||||
This section discusses how to make your own changes to Google Test.
|
||||
|
||||
### Testing Google Test Itself ###
|
||||
|
||||
To make sure your changes work as intended and don't break existing
|
||||
functionality, you'll want to compile and run Google Test's own tests.
|
||||
For that you can use CMake:
|
||||
|
||||
mkdir mybuild
|
||||
cd mybuild
|
||||
cmake -Dgtest_build_tests=ON ${GTEST_DIR}
|
||||
|
||||
Make sure you have Python installed, as some of Google Test's tests
|
||||
are written in Python. If the cmake command complains about not being
|
||||
able to find Python (`Could NOT find PythonInterp (missing:
|
||||
PYTHON_EXECUTABLE)`), try telling it explicitly where your Python
|
||||
executable can be found:
|
||||
|
||||
cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
|
||||
|
||||
Next, you can build Google Test and all of its own tests. On \*nix,
|
||||
this is usually done by 'make'. To run the tests, do
|
||||
|
||||
make test
|
||||
|
||||
All tests should pass.
|
||||
|
||||
### Regenerating Source Files ##
|
||||
|
||||
Some of Google Test's source files are generated from templates (not
|
||||
in the C++ sense) using a script.
|
||||
For example, the
|
||||
file include/gtest/internal/gtest-type-util.h.pump is used to generate
|
||||
gtest-type-util.h in the same directory.
|
||||
|
||||
You don't need to worry about regenerating the source files
|
||||
unless you need to modify them. You would then modify the
|
||||
corresponding `.pump` files and run the '[pump.py](googletest/scripts/pump.py)'
|
||||
generator script. See the [Pump Manual](googletest/docs/PumpManual.md).
|
||||
|
||||
## Developing Google Mock ###
|
||||
|
||||
This section discusses how to make your own changes to Google Mock.
|
||||
|
||||
#### Testing Google Mock Itself ####
|
||||
|
||||
To make sure your changes work as intended and don't break existing
|
||||
functionality, you'll want to compile and run Google Test's own tests.
|
||||
For that you'll need Autotools. First, make sure you have followed
|
||||
the instructions above to configure Google Mock.
|
||||
Then, create a build output directory and enter it. Next,
|
||||
|
||||
${GMOCK_DIR}/configure # try --help for more info
|
||||
|
||||
Once you have successfully configured Google Mock, the build steps are
|
||||
standard for GNU-style OSS packages.
|
||||
|
||||
make # Standard makefile following GNU conventions
|
||||
make check # Builds and runs all tests - all should pass.
|
||||
|
||||
Note that when building your project against Google Mock, you are building
|
||||
against Google Test as well. There is no need to configure Google Test
|
||||
separately.
|
@ -1,310 +1,14 @@
|
||||
# Automake file
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
# Nonstandard package files for distribution
|
||||
EXTRA_DIST = \
|
||||
CHANGES \
|
||||
CONTRIBUTORS \
|
||||
LICENSE \
|
||||
include/gtest/gtest-param-test.h.pump \
|
||||
include/gtest/internal/gtest-param-util-generated.h.pump \
|
||||
include/gtest/internal/gtest-tuple.h.pump \
|
||||
include/gtest/internal/gtest-type-util.h.pump \
|
||||
make/Makefile \
|
||||
scripts/fuse_gtest_files.py \
|
||||
scripts/gen_gtest_pred_impl.py \
|
||||
scripts/pump.py \
|
||||
scripts/test/Makefile
|
||||
|
||||
# gtest source files that we don't compile directly. They are
|
||||
# #included by gtest-all.cc.
|
||||
GTEST_SRC = \
|
||||
src/gtest-death-test.cc \
|
||||
src/gtest-filepath.cc \
|
||||
src/gtest-internal-inl.h \
|
||||
src/gtest-port.cc \
|
||||
src/gtest-printers.cc \
|
||||
src/gtest-test-part.cc \
|
||||
src/gtest-typed-test.cc \
|
||||
src/gtest.cc
|
||||
|
||||
EXTRA_DIST += $(GTEST_SRC)
|
||||
|
||||
# Sample files that we don't compile.
|
||||
EXTRA_DIST += \
|
||||
samples/prime_tables.h \
|
||||
samples/sample2_unittest.cc \
|
||||
samples/sample3_unittest.cc \
|
||||
samples/sample4_unittest.cc \
|
||||
samples/sample5_unittest.cc \
|
||||
samples/sample6_unittest.cc \
|
||||
samples/sample7_unittest.cc \
|
||||
samples/sample8_unittest.cc \
|
||||
samples/sample9_unittest.cc
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
# C++ test files that we don't compile directly.
|
||||
EXTRA_DIST += \
|
||||
test/gtest-death-test_ex_test.cc \
|
||||
test/gtest-death-test_test.cc \
|
||||
test/gtest-filepath_test.cc \
|
||||
test/gtest-linked_ptr_test.cc \
|
||||
test/gtest-listener_test.cc \
|
||||
test/gtest-message_test.cc \
|
||||
test/gtest-options_test.cc \
|
||||
test/gtest-param-test2_test.cc \
|
||||
test/gtest-param-test2_test.cc \
|
||||
test/gtest-param-test_test.cc \
|
||||
test/gtest-param-test_test.cc \
|
||||
test/gtest-param-test_test.h \
|
||||
test/gtest-port_test.cc \
|
||||
test/gtest_premature_exit_test.cc \
|
||||
test/gtest-printers_test.cc \
|
||||
test/gtest-test-part_test.cc \
|
||||
test/gtest-tuple_test.cc \
|
||||
test/gtest-typed-test2_test.cc \
|
||||
test/gtest-typed-test_test.cc \
|
||||
test/gtest-typed-test_test.h \
|
||||
test/gtest-unittest-api_test.cc \
|
||||
test/gtest_break_on_failure_unittest_.cc \
|
||||
test/gtest_catch_exceptions_test_.cc \
|
||||
test/gtest_color_test_.cc \
|
||||
test/gtest_env_var_test_.cc \
|
||||
test/gtest_environment_test.cc \
|
||||
test/gtest_filter_unittest_.cc \
|
||||
test/gtest_help_test_.cc \
|
||||
test/gtest_list_tests_unittest_.cc \
|
||||
test/gtest_main_unittest.cc \
|
||||
test/gtest_no_test_unittest.cc \
|
||||
test/gtest_output_test_.cc \
|
||||
test/gtest_pred_impl_unittest.cc \
|
||||
test/gtest_prod_test.cc \
|
||||
test/gtest_repeat_test.cc \
|
||||
test/gtest_shuffle_test_.cc \
|
||||
test/gtest_sole_header_test.cc \
|
||||
test/gtest_stress_test.cc \
|
||||
test/gtest_throw_on_failure_ex_test.cc \
|
||||
test/gtest_throw_on_failure_test_.cc \
|
||||
test/gtest_uninitialized_test_.cc \
|
||||
test/gtest_unittest.cc \
|
||||
test/gtest_unittest.cc \
|
||||
test/gtest_xml_outfile1_test_.cc \
|
||||
test/gtest_xml_outfile2_test_.cc \
|
||||
test/gtest_xml_output_unittest_.cc \
|
||||
test/production.cc \
|
||||
test/production.h
|
||||
# Build . before src so that our all-local and clean-local hooks kicks in at
|
||||
# the right time.
|
||||
SUBDIRS = googletest googlemock
|
||||
|
||||
# Python tests that we don't run.
|
||||
EXTRA_DIST += \
|
||||
test/gtest_break_on_failure_unittest.py \
|
||||
test/gtest_catch_exceptions_test.py \
|
||||
test/gtest_color_test.py \
|
||||
test/gtest_env_var_test.py \
|
||||
test/gtest_filter_unittest.py \
|
||||
test/gtest_help_test.py \
|
||||
test/gtest_list_tests_unittest.py \
|
||||
test/gtest_output_test.py \
|
||||
test/gtest_output_test_golden_lin.txt \
|
||||
test/gtest_shuffle_test.py \
|
||||
test/gtest_test_utils.py \
|
||||
test/gtest_throw_on_failure_test.py \
|
||||
test/gtest_uninitialized_test.py \
|
||||
test/gtest_xml_outfiles_test.py \
|
||||
test/gtest_xml_output_unittest.py \
|
||||
test/gtest_xml_test_utils.py
|
||||
|
||||
# CMake script
|
||||
EXTRA_DIST += \
|
||||
EXTRA_DIST = \
|
||||
BUILD.bazel \
|
||||
CMakeLists.txt \
|
||||
cmake/internal_utils.cmake
|
||||
|
||||
# MSVC project files
|
||||
EXTRA_DIST += \
|
||||
msvc/gtest-md.sln \
|
||||
msvc/gtest-md.vcproj \
|
||||
msvc/gtest.sln \
|
||||
msvc/gtest.vcproj \
|
||||
msvc/gtest_main-md.vcproj \
|
||||
msvc/gtest_main.vcproj \
|
||||
msvc/gtest_prod_test-md.vcproj \
|
||||
msvc/gtest_prod_test.vcproj \
|
||||
msvc/gtest_unittest-md.vcproj \
|
||||
msvc/gtest_unittest.vcproj
|
||||
|
||||
# xcode project files
|
||||
EXTRA_DIST += \
|
||||
xcode/Config/DebugProject.xcconfig \
|
||||
xcode/Config/FrameworkTarget.xcconfig \
|
||||
xcode/Config/General.xcconfig \
|
||||
xcode/Config/ReleaseProject.xcconfig \
|
||||
xcode/Config/StaticLibraryTarget.xcconfig \
|
||||
xcode/Config/TestTarget.xcconfig \
|
||||
xcode/Resources/Info.plist \
|
||||
xcode/Scripts/runtests.sh \
|
||||
xcode/Scripts/versiongenerate.py \
|
||||
xcode/gtest.xcodeproj/project.pbxproj
|
||||
|
||||
# xcode sample files
|
||||
EXTRA_DIST += \
|
||||
xcode/Samples/FrameworkSample/Info.plist \
|
||||
xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj \
|
||||
xcode/Samples/FrameworkSample/runtests.sh \
|
||||
xcode/Samples/FrameworkSample/widget.cc \
|
||||
xcode/Samples/FrameworkSample/widget.h \
|
||||
xcode/Samples/FrameworkSample/widget_test.cc
|
||||
|
||||
# C++Builder project files
|
||||
EXTRA_DIST += \
|
||||
codegear/gtest.cbproj \
|
||||
codegear/gtest.groupproj \
|
||||
codegear/gtest_all.cc \
|
||||
codegear/gtest_link.cc \
|
||||
codegear/gtest_main.cbproj \
|
||||
codegear/gtest_unittest.cbproj
|
||||
|
||||
# Distribute and install M4 macro
|
||||
m4datadir = $(datadir)/aclocal
|
||||
m4data_DATA = m4/gtest.m4
|
||||
EXTRA_DIST += $(m4data_DATA)
|
||||
|
||||
# We define the global AM_CPPFLAGS as everything we compile includes from these
|
||||
# directories.
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include
|
||||
|
||||
# Modifies compiler and linker flags for pthreads compatibility.
|
||||
if HAVE_PTHREADS
|
||||
AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1
|
||||
AM_LIBS = @PTHREAD_LIBS@
|
||||
else
|
||||
AM_CXXFLAGS = -DGTEST_HAS_PTHREAD=0
|
||||
endif
|
||||
|
||||
# Build rules for libraries.
|
||||
lib_LTLIBRARIES = lib/libgtest.la lib/libgtest_main.la
|
||||
|
||||
lib_libgtest_la_SOURCES = src/gtest-all.cc
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
include/gtest/gtest-death-test.h \
|
||||
include/gtest/gtest-message.h \
|
||||
include/gtest/gtest-param-test.h \
|
||||
include/gtest/gtest-printers.h \
|
||||
include/gtest/gtest-spi.h \
|
||||
include/gtest/gtest-test-part.h \
|
||||
include/gtest/gtest-typed-test.h \
|
||||
include/gtest/gtest.h \
|
||||
include/gtest/gtest_pred_impl.h \
|
||||
include/gtest/gtest_prod.h
|
||||
|
||||
pkginclude_internaldir = $(pkgincludedir)/internal
|
||||
pkginclude_internal_HEADERS = \
|
||||
include/gtest/internal/gtest-death-test-internal.h \
|
||||
include/gtest/internal/gtest-filepath.h \
|
||||
include/gtest/internal/gtest-internal.h \
|
||||
include/gtest/internal/gtest-linked_ptr.h \
|
||||
include/gtest/internal/gtest-param-util-generated.h \
|
||||
include/gtest/internal/gtest-param-util.h \
|
||||
include/gtest/internal/gtest-port.h \
|
||||
include/gtest/internal/gtest-port-arch.h \
|
||||
include/gtest/internal/gtest-string.h \
|
||||
include/gtest/internal/gtest-tuple.h \
|
||||
include/gtest/internal/gtest-type-util.h \
|
||||
include/gtest/internal/custom/gtest.h \
|
||||
include/gtest/internal/custom/gtest-port.h \
|
||||
include/gtest/internal/custom/gtest-printers.h
|
||||
|
||||
lib_libgtest_main_la_SOURCES = src/gtest_main.cc
|
||||
lib_libgtest_main_la_LIBADD = lib/libgtest.la
|
||||
|
||||
# Bulid rules for samples and tests. Automake's naming for some of
|
||||
# these variables isn't terribly obvious, so this is a brief
|
||||
# reference:
|
||||
#
|
||||
# TESTS -- Programs run automatically by "make check"
|
||||
# check_PROGRAMS -- Programs built by "make check" but not necessarily run
|
||||
|
||||
noinst_LTLIBRARIES = samples/libsamples.la
|
||||
|
||||
samples_libsamples_la_SOURCES = \
|
||||
samples/sample1.cc \
|
||||
samples/sample1.h \
|
||||
samples/sample2.cc \
|
||||
samples/sample2.h \
|
||||
samples/sample3-inl.h \
|
||||
samples/sample4.cc \
|
||||
samples/sample4.h
|
||||
|
||||
TESTS=
|
||||
TESTS_ENVIRONMENT = GTEST_SOURCE_DIR="$(srcdir)/test" \
|
||||
GTEST_BUILD_DIR="$(top_builddir)/test"
|
||||
check_PROGRAMS=
|
||||
|
||||
# A simple sample on using gtest.
|
||||
TESTS += samples/sample1_unittest
|
||||
check_PROGRAMS += samples/sample1_unittest
|
||||
samples_sample1_unittest_SOURCES = samples/sample1_unittest.cc
|
||||
samples_sample1_unittest_LDADD = lib/libgtest_main.la \
|
||||
lib/libgtest.la \
|
||||
samples/libsamples.la
|
||||
|
||||
# Another sample. It also verifies that libgtest works.
|
||||
TESTS += samples/sample10_unittest
|
||||
check_PROGRAMS += samples/sample10_unittest
|
||||
samples_sample10_unittest_SOURCES = samples/sample10_unittest.cc
|
||||
samples_sample10_unittest_LDADD = lib/libgtest.la
|
||||
|
||||
# This tests most constructs of gtest and verifies that libgtest_main
|
||||
# and libgtest work.
|
||||
TESTS += test/gtest_all_test
|
||||
check_PROGRAMS += test/gtest_all_test
|
||||
test_gtest_all_test_SOURCES = test/gtest_all_test.cc
|
||||
test_gtest_all_test_LDADD = lib/libgtest_main.la \
|
||||
lib/libgtest.la
|
||||
|
||||
# Tests that fused gtest files compile and work.
|
||||
FUSED_GTEST_SRC = \
|
||||
fused-src/gtest/gtest-all.cc \
|
||||
fused-src/gtest/gtest.h \
|
||||
fused-src/gtest/gtest_main.cc
|
||||
|
||||
if HAVE_PYTHON
|
||||
TESTS += test/fused_gtest_test
|
||||
check_PROGRAMS += test/fused_gtest_test
|
||||
test_fused_gtest_test_SOURCES = $(FUSED_GTEST_SRC) \
|
||||
samples/sample1.cc samples/sample1_unittest.cc
|
||||
test_fused_gtest_test_CPPFLAGS = -I"$(srcdir)/fused-src"
|
||||
|
||||
# Build rules for putting fused Google Test files into the distribution
|
||||
# package. The user can also create those files by manually running
|
||||
# scripts/fuse_gtest_files.py.
|
||||
$(test_fused_gtest_test_SOURCES): fused-gtest
|
||||
|
||||
fused-gtest: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \
|
||||
$(GTEST_SRC) src/gtest-all.cc src/gtest_main.cc \
|
||||
scripts/fuse_gtest_files.py
|
||||
mkdir -p "$(srcdir)/fused-src"
|
||||
chmod -R u+w "$(srcdir)/fused-src"
|
||||
rm -f "$(srcdir)/fused-src/gtest/gtest-all.cc"
|
||||
rm -f "$(srcdir)/fused-src/gtest/gtest.h"
|
||||
"$(srcdir)/scripts/fuse_gtest_files.py" "$(srcdir)/fused-src"
|
||||
cp -f "$(srcdir)/src/gtest_main.cc" "$(srcdir)/fused-src/gtest/"
|
||||
|
||||
maintainer-clean-local:
|
||||
rm -rf "$(srcdir)/fused-src"
|
||||
endif
|
||||
|
||||
# Death tests may produce core dumps in the build directory. In case
|
||||
# this happens, clean them to keep distcleancheck happy.
|
||||
CLEANFILES = core
|
||||
|
||||
# Disables 'make install' as installing a compiled version of Google
|
||||
# Test can lead to undefined behavior due to violation of the
|
||||
# One-Definition Rule.
|
||||
|
||||
install-exec-local:
|
||||
echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
|
||||
false
|
||||
|
||||
install-data-local:
|
||||
echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
|
||||
false
|
||||
README.md \
|
||||
WORKSPACE
|
||||
|
@ -1,280 +1,132 @@
|
||||
|
||||
### Generic Build Instructions ###
|
||||
# Google Test #
|
||||
|
||||
#### Setup ####
|
||||
[![Build Status](https://api.travis-ci.org/google/googletest.svg?branch=master)](https://travis-ci.org/google/googletest)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/4o38plt0xbo1ubc8/branch/master?svg=true)](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master)
|
||||
|
||||
To build Google Test and your tests that use it, you need to tell your
|
||||
build system where to find its headers and source files. The exact
|
||||
way to do it depends on which build system you use, and is usually
|
||||
straightforward.
|
||||
**PR FREEZE COMING SOON**
|
||||
|
||||
#### Build ####
|
||||
We are working on a large refactoring that would make it hard to accept external PRs. *Really Soon Now* we will not be accepting new PRs until the refactoring has been completed.
|
||||
|
||||
Suppose you put Google Test in directory `${GTEST_DIR}`. To build it,
|
||||
create a library build target (or a project as called by Visual Studio
|
||||
and Xcode) to compile
|
||||
**Future Plans**:
|
||||
* 1.8.x Release - [the 1.8.x](https://github.com/google/googletest/releases/tag/release-1.8.1) is the last release that works with pre-C++11 compilers. The 1.8.x will not accept any requests for any new features and any bugfix requests will only be accepted if proven "critical"
|
||||
* Post 1.8.x - work to improve/cleanup/pay technical debt. When this work is completed there will be a 1.9.x tagged release
|
||||
* Post 1.9.x googletest will follow [Abseil Live at Head philosophy](https://abseil.io/about/philosophy)
|
||||
|
||||
${GTEST_DIR}/src/gtest-all.cc
|
||||
|
||||
with `${GTEST_DIR}/include` in the system header search path and `${GTEST_DIR}`
|
||||
in the normal header search path. Assuming a Linux-like system and gcc,
|
||||
something like the following will do:
|
||||
Welcome to **Google Test**, Google's C++ test framework!
|
||||
|
||||
g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
|
||||
-pthread -c ${GTEST_DIR}/src/gtest-all.cc
|
||||
ar -rv libgtest.a gtest-all.o
|
||||
This repository is a merger of the formerly separate GoogleTest and
|
||||
GoogleMock projects. These were so closely related that it makes sense to
|
||||
maintain and release them together.
|
||||
|
||||
(We need `-pthread` as Google Test uses threads.)
|
||||
Please subscribe to the mailing list at googletestframework@googlegroups.com for questions, discussions, and development.
|
||||
There is also an IRC channel on [OFTC](https://webchat.oftc.net/) (irc.oftc.net) #gtest available.
|
||||
|
||||
Next, you should compile your test source file with
|
||||
`${GTEST_DIR}/include` in the system header search path, and link it
|
||||
with gtest and any other necessary libraries:
|
||||
Getting started information for **Google Test** is available in the
|
||||
[Google Test Primer](googletest/docs/primer.md) documentation.
|
||||
|
||||
g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \
|
||||
-o your_test
|
||||
**Google Mock** is an extension to Google Test for writing and using C++ mock
|
||||
classes. See the separate [Google Mock documentation](googlemock/README.md).
|
||||
|
||||
As an example, the make/ directory contains a Makefile that you can
|
||||
use to build Google Test on systems where GNU make is available
|
||||
(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
|
||||
Test's own tests. Instead, it just builds the Google Test library and
|
||||
a sample test. You can use it as a starting point for your own build
|
||||
script.
|
||||
More detailed documentation for googletest (including build instructions) are
|
||||
in its interior [googletest/README.md](googletest/README.md) file.
|
||||
|
||||
If the default settings are correct for your environment, the
|
||||
following commands should succeed:
|
||||
## Features ##
|
||||
|
||||
cd ${GTEST_DIR}/make
|
||||
make
|
||||
./sample1_unittest
|
||||
* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
|
||||
* Test discovery.
|
||||
* A rich set of assertions.
|
||||
* User-defined assertions.
|
||||
* Death tests.
|
||||
* Fatal and non-fatal failures.
|
||||
* Value-parameterized tests.
|
||||
* Type-parameterized tests.
|
||||
* Various options for running the tests.
|
||||
* XML test report generation.
|
||||
|
||||
If you see errors, try to tweak the contents of `make/Makefile` to make
|
||||
them go away. There are instructions in `make/Makefile` on how to do
|
||||
it.
|
||||
## Platforms ##
|
||||
|
||||
### Using CMake ###
|
||||
Google test has been used on a variety of platforms:
|
||||
|
||||
Google Test comes with a CMake build script (
|
||||
[CMakeLists.txt](CMakeLists.txt)) that can be used on a wide range of platforms ("C" stands for
|
||||
cross-platform.). If you don't have CMake installed already, you can
|
||||
download it for free from <http://www.cmake.org/>.
|
||||
* Linux
|
||||
* Mac OS X
|
||||
* Windows
|
||||
* Cygwin
|
||||
* MinGW
|
||||
* Windows Mobile
|
||||
* Symbian
|
||||
|
||||
CMake works by generating native makefiles or build projects that can
|
||||
be used in the compiler environment of your choice. The typical
|
||||
workflow starts with:
|
||||
## Who Is Using Google Test? ##
|
||||
|
||||
mkdir mybuild # Create a directory to hold the build output.
|
||||
cd mybuild
|
||||
cmake ${GTEST_DIR} # Generate native build scripts.
|
||||
In addition to many internal projects at Google, Google Test is also used by
|
||||
the following notable projects:
|
||||
|
||||
If you want to build Google Test's samples, you should replace the
|
||||
last command with
|
||||
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome
|
||||
browser and Chrome OS).
|
||||
* The [LLVM](http://llvm.org/) compiler.
|
||||
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
|
||||
interchange format.
|
||||
* The [OpenCV](http://opencv.org/) computer vision library.
|
||||
* [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only, dependency-free deep learning framework in C++11.
|
||||
|
||||
cmake -Dgtest_build_samples=ON ${GTEST_DIR}
|
||||
## Related Open Source Projects ##
|
||||
|
||||
If you are on a \*nix system, you should now see a Makefile in the
|
||||
current directory. Just type 'make' to build gtest.
|
||||
[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based automated test-runner and Graphical User Interface with powerful features for Windows and Linux platforms.
|
||||
|
||||
If you use Windows and have Visual Studio installed, a `gtest.sln` file
|
||||
and several `.vcproj` files will be created. You can then build them
|
||||
using Visual Studio.
|
||||
[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that runs
|
||||
your test binary, allows you to track its progress via a progress bar, and
|
||||
displays a list of test failures. Clicking on one shows failure text. Google
|
||||
Test UI is written in C#.
|
||||
|
||||
On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
|
||||
[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
|
||||
listener for Google Test that implements the
|
||||
[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
|
||||
result output. If your test runner understands TAP, you may find it useful.
|
||||
|
||||
### Legacy Build Scripts ###
|
||||
[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
|
||||
runs tests from your binary in parallel to provide significant speed-up.
|
||||
|
||||
Before settling on CMake, we have been providing hand-maintained build
|
||||
projects/scripts for Visual Studio, Xcode, and Autotools. While we
|
||||
continue to provide them for convenience, they are not actively
|
||||
maintained any more. We highly recommend that you follow the
|
||||
instructions in the previous two sections to integrate Google Test
|
||||
with your existing build system.
|
||||
[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter) is a VS Code extension allowing to view Google Tests in a tree view, and run/debug your tests.
|
||||
|
||||
If you still need to use the legacy build scripts, here's how:
|
||||
## Requirements ##
|
||||
|
||||
The msvc\ folder contains two solutions with Visual C++ projects.
|
||||
Open the `gtest.sln` or `gtest-md.sln` file using Visual Studio, and you
|
||||
are ready to build Google Test the same way you build any Visual
|
||||
Studio project. Files that have names ending with -md use DLL
|
||||
versions of Microsoft runtime libraries (the /MD or the /MDd compiler
|
||||
option). Files without that suffix use static versions of the runtime
|
||||
libraries (the /MT or the /MTd option). Please note that one must use
|
||||
the same option to compile both gtest and the test code. If you use
|
||||
Visual Studio 2005 or above, we recommend the -md version as /MD is
|
||||
the default for new projects in these versions of Visual Studio.
|
||||
Google Test is designed to have fairly minimal requirements to build
|
||||
and use with your projects, but there are some. Currently, we support
|
||||
Linux, Windows, Mac OS X, and Cygwin. We will also make our best
|
||||
effort to support other platforms (e.g. Solaris, AIX, and z/OS).
|
||||
However, since core members of the Google Test project have no access
|
||||
to these platforms, Google Test may have outstanding issues there. If
|
||||
you notice any problems on your platform, please notify
|
||||
[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework). Patches for fixing them are
|
||||
even more welcome!
|
||||
|
||||
On Mac OS X, open the `gtest.xcodeproj` in the `xcode/` folder using
|
||||
Xcode. Build the "gtest" target. The universal binary framework will
|
||||
end up in your selected build directory (selected in the Xcode
|
||||
"Preferences..." -> "Building" pane and defaults to xcode/build).
|
||||
Alternatively, at the command line, enter:
|
||||
### Linux Requirements ###
|
||||
|
||||
xcodebuild
|
||||
These are the base requirements to build and use Google Test from a source
|
||||
package (as described below):
|
||||
|
||||
This will build the "Release" configuration of gtest.framework in your
|
||||
default build location. See the "xcodebuild" man page for more
|
||||
information about building different configurations and building in
|
||||
different locations.
|
||||
* GNU-compatible Make or gmake
|
||||
* POSIX-standard shell
|
||||
* POSIX(-2) Regular Expressions (regex.h)
|
||||
* A C++11-standard-compliant compiler
|
||||
|
||||
If you wish to use the Google Test Xcode project with Xcode 4.x and
|
||||
above, you need to either:
|
||||
### Windows Requirements ###
|
||||
|
||||
* update the SDK configuration options in xcode/Config/General.xconfig.
|
||||
Comment options `SDKROOT`, `MACOS_DEPLOYMENT_TARGET`, and `GCC_VERSION`. If
|
||||
you choose this route you lose the ability to target earlier versions
|
||||
of MacOS X.
|
||||
* Install an SDK for an earlier version. This doesn't appear to be
|
||||
supported by Apple, but has been reported to work
|
||||
(http://stackoverflow.com/questions/5378518).
|
||||
* Microsoft Visual C++ 2015 or newer
|
||||
|
||||
### Tweaking Google Test ###
|
||||
### Cygwin Requirements ###
|
||||
|
||||
Google Test can be used in diverse environments. The default
|
||||
configuration may not work (or may not work well) out of the box in
|
||||
some environments. However, you can easily tweak Google Test by
|
||||
defining control macros on the compiler command line. Generally,
|
||||
these macros are named like `GTEST_XYZ` and you define them to either 1
|
||||
or 0 to enable or disable a certain feature.
|
||||
* Cygwin v1.5.25-14 or newer
|
||||
|
||||
We list the most frequently used macros below. For a complete list,
|
||||
see file [include/gtest/internal/gtest-port.h](include/gtest/internal/gtest-port.h).
|
||||
### Mac OS X Requirements ###
|
||||
|
||||
### Choosing a TR1 Tuple Library ###
|
||||
* Mac OS X v10.4 Tiger or newer
|
||||
* Xcode Developer Tools
|
||||
|
||||
Some Google Test features require the C++ Technical Report 1 (TR1)
|
||||
tuple library, which is not yet available with all compilers. The
|
||||
good news is that Google Test implements a subset of TR1 tuple that's
|
||||
enough for its own need, and will automatically use this when the
|
||||
compiler doesn't provide TR1 tuple.
|
||||
## Contributing change
|
||||
|
||||
Usually you don't need to care about which tuple library Google Test
|
||||
uses. However, if your project already uses TR1 tuple, you need to
|
||||
tell Google Test to use the same TR1 tuple library the rest of your
|
||||
project uses, or the two tuple implementations will clash. To do
|
||||
that, add
|
||||
Please read the [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on
|
||||
how to contribute to this project.
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=0
|
||||
|
||||
to the compiler flags while compiling Google Test and your tests. If
|
||||
you want to force Google Test to use its own tuple library, just add
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=1
|
||||
|
||||
to the compiler flags instead.
|
||||
|
||||
If you don't want Google Test to use tuple at all, add
|
||||
|
||||
-DGTEST_HAS_TR1_TUPLE=0
|
||||
|
||||
and all features using tuple will be disabled.
|
||||
|
||||
### Multi-threaded Tests ###
|
||||
|
||||
Google Test is thread-safe where the pthread library is available.
|
||||
After `#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE`
|
||||
macro to see whether this is the case (yes if the macro is `#defined` to
|
||||
1, no if it's undefined.).
|
||||
|
||||
If Google Test doesn't correctly detect whether pthread is available
|
||||
in your environment, you can force it with
|
||||
|
||||
-DGTEST_HAS_PTHREAD=1
|
||||
|
||||
or
|
||||
|
||||
-DGTEST_HAS_PTHREAD=0
|
||||
|
||||
When Google Test uses pthread, you may need to add flags to your
|
||||
compiler and/or linker to select the pthread library, or you'll get
|
||||
link errors. If you use the CMake script or the deprecated Autotools
|
||||
script, this is taken care of for you. If you use your own build
|
||||
script, you'll need to read your compiler and linker's manual to
|
||||
figure out what flags to add.
|
||||
|
||||
### As a Shared Library (DLL) ###
|
||||
|
||||
Google Test is compact, so most users can build and link it as a
|
||||
static library for the simplicity. You can choose to use Google Test
|
||||
as a shared library (known as a DLL on Windows) if you prefer.
|
||||
|
||||
To compile *gtest* as a shared library, add
|
||||
|
||||
-DGTEST_CREATE_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags. You'll also need to tell the linker to produce
|
||||
a shared library instead - consult your linker's manual for how to do
|
||||
it.
|
||||
|
||||
To compile your *tests* that use the gtest shared library, add
|
||||
|
||||
-DGTEST_LINKED_AS_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags.
|
||||
|
||||
Note: while the above steps aren't technically necessary today when
|
||||
using some compilers (e.g. GCC), they may become necessary in the
|
||||
future, if we decide to improve the speed of loading the library (see
|
||||
<http://gcc.gnu.org/wiki/Visibility> for details). Therefore you are
|
||||
recommended to always add the above flags when using Google Test as a
|
||||
shared library. Otherwise a future release of Google Test may break
|
||||
your build script.
|
||||
|
||||
### Avoiding Macro Name Clashes ###
|
||||
|
||||
In C++, macros don't obey namespaces. Therefore two libraries that
|
||||
both define a macro of the same name will clash if you `#include` both
|
||||
definitions. In case a Google Test macro clashes with another
|
||||
library, you can force Google Test to rename its macro to avoid the
|
||||
conflict.
|
||||
|
||||
Specifically, if both Google Test and some other code define macro
|
||||
FOO, you can add
|
||||
|
||||
-DGTEST_DONT_DEFINE_FOO=1
|
||||
|
||||
to the compiler flags to tell Google Test to change the macro's name
|
||||
from `FOO` to `GTEST_FOO`. Currently `FOO` can be `FAIL`, `SUCCEED`,
|
||||
or `TEST`. For example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll
|
||||
need to write
|
||||
|
||||
GTEST_TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
instead of
|
||||
|
||||
TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
in order to define a test.
|
||||
|
||||
## Developing Google Test ##
|
||||
|
||||
This section discusses how to make your own changes to Google Test.
|
||||
|
||||
### Testing Google Test Itself ###
|
||||
|
||||
To make sure your changes work as intended and don't break existing
|
||||
functionality, you'll want to compile and run Google Test's own tests.
|
||||
For that you can use CMake:
|
||||
|
||||
mkdir mybuild
|
||||
cd mybuild
|
||||
cmake -Dgtest_build_tests=ON ${GTEST_DIR}
|
||||
|
||||
Make sure you have Python installed, as some of Google Test's tests
|
||||
are written in Python. If the cmake command complains about not being
|
||||
able to find Python (`Could NOT find PythonInterp (missing:
|
||||
PYTHON_EXECUTABLE)`), try telling it explicitly where your Python
|
||||
executable can be found:
|
||||
|
||||
cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
|
||||
|
||||
Next, you can build Google Test and all of its own tests. On \*nix,
|
||||
this is usually done by 'make'. To run the tests, do
|
||||
|
||||
make test
|
||||
|
||||
All tests should pass.
|
||||
|
||||
Normally you don't need to worry about regenerating the source files,
|
||||
unless you need to modify them. In that case, you should modify the
|
||||
corresponding .pump files instead and run the pump.py Python script to
|
||||
regenerate them. You can find pump.py in the [scripts/](scripts/) directory.
|
||||
Read the [Pump manual](docs/PumpManual.md) for how to use it.
|
||||
Happy testing!
|
||||
|
@ -0,0 +1,10 @@
|
||||
workspace(name = "com_google_googletest")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# Abseil
|
||||
http_archive(
|
||||
name = "com_google_absl",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"],
|
||||
strip_prefix = "abseil-cpp-master",
|
||||
)
|
@ -0,0 +1,103 @@
|
||||
version: '{build}'
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017"
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017 Win64"
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
generator: "Visual Studio 14 2015"
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
generator: "Visual Studio 14 2015 Win64"
|
||||
|
||||
- compiler: gcc-6.3.0-posix
|
||||
generator: "MinGW Makefiles"
|
||||
cxx_path: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin'
|
||||
enabled_on_pr: yes
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
||||
build:
|
||||
verbosity: minimal
|
||||
|
||||
install:
|
||||
- ps: |
|
||||
Write-Output "Compiler: $env:compiler"
|
||||
Write-Output "Generator: $env:generator"
|
||||
Write-Output "Env:Configuation: $env:configuration"
|
||||
Write-Output "Env: $env"
|
||||
if (-not (Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER)) {
|
||||
Write-Output "This is *NOT* a pull request build"
|
||||
} else {
|
||||
Write-Output "This is a pull request build"
|
||||
if (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes") {
|
||||
Write-Output "PR builds are *NOT* explicitly enabled"
|
||||
}
|
||||
}
|
||||
|
||||
# git bash conflicts with MinGW makefiles
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
$env:path = $env:path.replace("C:\Program Files\Git\usr\bin;", "")
|
||||
if ($env:cxx_path -ne "") {
|
||||
$env:path += ";$env:cxx_path"
|
||||
}
|
||||
}
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
}
|
||||
md _build -Force | Out-Null
|
||||
cd _build
|
||||
|
||||
$conf = if ($env:generator -eq "MinGW Makefiles") {"-DCMAKE_BUILD_TYPE=$env:configuration"} else {"-DCMAKE_CONFIGURATION_TYPES=Debug;Release"}
|
||||
# Disable test for MinGW (gtest tests fail, gmock tests can not build)
|
||||
$gtest_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgtest_build_tests=OFF"} else {"-Dgtest_build_tests=ON"}
|
||||
$gmock_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgmock_build_tests=OFF"} else {"-Dgmock_build_tests=ON"}
|
||||
& cmake -G "$env:generator" $conf -Dgtest_build_samples=ON $gtest_build_tests $gmock_build_tests ..
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
$cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"}
|
||||
& cmake --build . --config $env:configuration -- $cmake_parallel
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
|
||||
|
||||
skip_commits:
|
||||
files:
|
||||
- '**/*.md'
|
||||
|
||||
test_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
}
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
return # No test available for MinGW
|
||||
}
|
||||
& ctest -C $env:configuration --timeout 600 --output-on-failure
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
name: logs
|
||||
- path: '_build/Testing/**/*.xml'
|
||||
name: test_results
|
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -e
|
||||
|
||||
. ci/get-nprocessors.sh
|
||||
|
||||
# Create the configuration script
|
||||
autoreconf -i
|
||||
|
||||
# Run in a subdirectory to keep the sources clean
|
||||
mkdir build || true
|
||||
cd build
|
||||
../configure
|
||||
|
||||
make -j ${NPROCESSORS:-2}
|
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -e
|
||||
|
||||
bazel build --curses=no //...:all
|
||||
bazel test --curses=no //...:all
|
||||
bazel test --curses=no //...:all --define absl=1
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue