text:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright 2007 University of Washington
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors:  Craig Dowell (craigdo@ee.washington.edu)
 *           Tom Henderson (tomhend@u.washington.edu)
 */

#ifndef GLOBAL_ROUTE_MANAGER_IMPL_H
#define GLOBAL_ROUTE_MANAGER_IMPL_H

#include <stdint.h>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include "ns3/object.h"
#include "ns3/ptr.h"
#include "ns3/ipv4-address.h"
#include "global-router-interface.h"

namespace ns3 {

const uint32_t SPF_INFINITY = 0xffffffff; //!< "infinite" distance between nodes

class CandidateQueue;
class Ipv4GlobalRouting;

/**
 * @brief Vertex used in shortest path first (SPF) computations. See \RFC{2328},
 * Section 16.
 *
 * Each router in the simulation is associated with an SPFVertex object.  When
 * calculating routes, each of these routers is, in turn, chosen as the "root"
 * of the calculation and routes to all of the other routers are eventually
 * saved in the routing tables of each of the chosen nodes.  Each of these
 * routers in the calculation has an associated SPFVertex.
 *
 * The "Root" vertex is the SPFVertex representing the router that is having
 * its routing tables set.  The SPFVertex objects representing other routers
 * or networks in the simulation are arranged in the SPF tree.  It is this
 * tree that represents the Shortest Paths to the other networks.
 *
 * Each SPFVertex has a pointer to the Global Router Link State Advertisement
 * (LSA) that its underlying router has exported.  Within these LSAs are
 * Global Router Link Records that describe the point to point links from the
 * underlying router to other nodes (represented by other SPFVertex objects)
 * in the simulation topology.  The combination of the arrangement of the
 * SPFVertex objects in the SPF tree, along with the details of the link
 * records that connect them provide the information required to construct the
 * required routes.
 */
class SPFVertex
{
public:
/**
 * @brief Enumeration of the possible types of SPFVertex objects.
 * @internal
 *
 * Currently we use VertexRouter to identify objects that represent a router
 * in the simulation topology, and VertexNetwork to identify objects that
 * represent a network.
 */
  enum VertexType {
    VertexUnknown = 0,  /**< Uninitialized Link Record */
    VertexRouter,       /**< Vertex representing a router in the topology */
    VertexNetwork       /**< Vertex representing a network in the topology */
  };

/**
 * @brief Construct an empty ("uninitialized") SPFVertex (Shortest Path First
 * Vertex).
 * @internal
 *
 * The Vertex Type is set to VertexUnknown, the Vertex ID is set to
 * 255.255.255.255, and the distance from root is set to infinity
 * (UINT32_MAX).  The referenced Link State Advertisement (LSA) is set to
 * null as is the parent SPFVertex.  The outgoing interface index is set to
 * infinity, the next hop address is set to 0.0.0.0 and the list of children
 * of the SPFVertex is initialized to empty.
 *
 * @see VertexType
 */
  SPFVertex();

/**
 * @brief Construct an initialized SPFVertex (Shortest Path First Vertex).
 * @internal
 *
 * The Vertex Type is initialized to VertexRouter and the Vertex ID is found
 * from the Link State ID of the Link State Advertisement (LSA) passed as a
 * parameter.  The Link State ID is set to the Router ID of the advertising
 * router.  The referenced LSA (m_lsa) is set to the given LSA.  Other than
 * these members, initialization is as in the default constructor.
 * of the SPFVertex is initialized to empty.
 *
 * @see SPFVertex::SPFVertex ()
 * @see VertexType
 * @see GlobalRoutingLSA
 * @param lsa The Link State Advertisement used for finding initial values.
 */
  SPFVertex(GlobalRoutingLSA* lsa);

/**
 * @brief Destroy an SPFVertex (Shortest Path First Vertex).
 * @internal
 *
 * The children vertices of the SPFVertex are recursively deleted.
 *
 * @see SPFVertex::SPFVertex ()
 */
  ~SPFVertex();

/**
 * @brief Get the Vertex Type field of a SPFVertex object.
 * @internal
 *
 * The Vertex Type describes the kind of simulation object a given SPFVertex
 * represents.
 *
 * @see VertexType
 * @returns The VertexType of the current SPFVertex object.
 */
  VertexType GetVertexType (void) const;

/**
 * @brief Set the Vertex Type field of a SPFVertex object.
 * @internal
 *
 * The Vertex Type describes the kind of simulation object a given SPFVertex
 * represents.
 *
 * @see VertexType
 * @param type The new VertexType for the current SPFVertex object.
 */
  void SetVertexType (VertexType type);

/**
 * @brief Get the Vertex ID field of a SPFVertex object.
 * @internal
 *
 * The Vertex ID uniquely identifies the simulation object a given SPFVertex
 * represents.  Typically, this is the Router ID for SPFVertex objects
 * representing routers, and comes from the Link State Advertisement of a
 * router aggregated to a node in the simulation.  These IDs are allocated
 * automatically by the routing environment and look like IP addresses
 * beginning at 0.0.0.0 and monotonically increasing as new routers are
 * instantiated.
 *
 * @returns The Ipv4Address Vertex ID of the current SPFVertex object.
 */
  Ipv4Address GetVertexId (void) const;

/**
 * @brief Set the Vertex ID field of a SPFVertex object.
 * @internal
 *
 * The Vertex ID uniquely identifies the simulation object a given SPFVertex
 * represents.  Typically, this is the Router ID for SPFVertex objects
 * representing routers, and comes from the Link State Advertisement of a
 * router aggregated to a node in the simulation.  These IDs are allocated
 * automatically by the routing environment and look like IP addresses
 * beginning at 0.0.0.0 and monotonically increase as new routers are
 * instantiated.  This method is an explicit override of the automatically
 * generated value.
 *
 * @param id The new Ipv4Address Vertex ID for the current SPFVertex object.
 */
  void SetVertexId (Ipv4Address id);

/**
 * @brief Get the Global Router Link State Advertisement returned by the
 * Global Router represented by this SPFVertex during the route discovery
 * process.
 * @internal
 *
 * @see GlobalRouter
 * @see GlobalRoutingLSA
 * @see GlobalRouter::DiscoverLSAs ()
 * @returns A pointer to the GlobalRoutingLSA found by the router represented
 * by this SPFVertex object.
 */
  GlobalRoutingLSA* GetLSA (void) const;

/**
 * @brief Set the Global Router Link State Advertisement returned by the
 * Global Router represented by this SPFVertex during the route discovery
 * process.
 * @internal
 *
 * @see SPFVertex::GetLSA ()
 * @see GlobalRouter
 * @see GlobalRoutingLSA
 * @see GlobalRouter::DiscoverLSAs ()
 * @warning Ownership of the LSA is transferred to the "this" SPFVertex.  You
 * must not delete the LSA after calling this method.
 * @param lsa A pointer to the GlobalRoutingLSA.
 */
  void SetLSA (GlobalRoutingLSA* lsa);

/**
 * @brief Get the distance from the root vertex to "this" SPFVertex object.
 * @internal
 *
 * Each router in the simulation is associated with an SPFVertex object.  When
 * calculating routes, each of these routers is, in turn, chosen as the "root"
 * of the calculation and routes to all of the other routers are eventually
 * saved in the routing tables of each of the chosen nodes.  Each of these
 * routers in the calculation has an associated SPFVertex.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set.  The "this" SPFVertex is the vertex to which
 * a route is being calculated from the root.  The distance from the root that
 * we're asking for is the number of hops from the root vertex to the vertex
 * in question.
 *
 * The distance is calculated during route discovery and is stored in a
 * member variable.  This method simply fetches that value.
 *
 * @returns The distance, in hops, from the root SPFVertex to "this" SPFVertex.
 */
  uint32_t GetDistanceFromRoot (void) const;

/**
 * @brief Set the distance from the root vertex to "this" SPFVertex object.
 * @internal
 *
 * Each router in the simulation is associated with an SPFVertex object.  When
 * calculating routes, each of these routers is, in turn, chosen as the "root"
 * of the calculation and routes to all of the other routers are eventually
 * saved in the routing tables of each of the chosen nodes.  Each of these
 * routers in the calculation has an associated SPFVertex.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set.  The "this" SPFVertex is the vertex to which
 * a route is being calculated from the root.  The distance from the root that
 * we're asking for is the number of hops from the root vertex to the vertex
 * in question.
 *
 * @param distance The distance, in hops, from the root SPFVertex to "this"
 * SPFVertex.
 */
  void SetDistanceFromRoot (uint32_t distance);

/**
 * @brief Set the IP address and outgoing interface index that should be used
 * to begin forwarding packets from the root SPFVertex to "this" SPFVertex.
 * @internal
 *
 * Each router node in the simulation is associated with an SPFVertex object.
 * When calculating routes, each of these routers is, in turn, chosen as the
 * "root" of the calculation and routes to all of the other routers are
 * eventually saved in the routing tables of each of the chosen nodes.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set.  The "this" SPFVertex is the vertex that
 * represents the host or network to which a route is being calculated from
 * the root.  The IP address that we're asking for is the address on the
 * remote side of a link off of the root node that should be used as the
 * destination for packets along the path to "this" vertex.
 *
 * When initializing the root SPFVertex, the IP address used when forwarding
 * packets is determined by examining the Global Router Link Records of the
 * Link State Advertisement generated by the root node's GlobalRouter.  This
 * address is used to forward packets off of the root's network down those
 * links.  As other vertices / nodes are discovered which are further away
 * from the root, they will be accessible down one of the paths via a link
 * described by one of these Global Router Link Records.
 *
 * To forward packets to these hosts or networks, the root node must begin
 * the forwarding process by sending the packets to a first hop router down
 * an interface.  This means that the first hop address and interface ID must
 * be the same for all downstream SPFVertices.  We call this "inheriting"
 * the interface and next hop.
 *
 * In this method we are telling the root node which exit direction it should send
 * should I send a packet to the network or host represented by 'this' SPFVertex.
 *
 * @see GlobalRouter
 * @see GlobalRoutingLSA
 * @see GlobalRoutingLinkRecord
 * @param nextHop The IP address to use when forwarding packets to the host
 * or network represented by "this" SPFVertex.
 * @param id The interface index to use when forwarding packets to the host or
 * network represented by "this" SPFVertex.
 */
  void SetRootExitDirection (Ipv4Address nextHop, int32_t id = SPF_INFINITY);

  typedef std::pair<Ipv4Address, int32_t> NodeExit_t; //!< IPv4 / interface container for exit nodes.

/**
 * @brief Set the IP address and outgoing interface index that should be used
 * to begin forwarding packets from the root SPFVertex to "this" SPFVertex.
 * @internal
 *
 * Each router node in the simulation is associated with an SPFVertex object.
 * When calculating routes, each of these routers is, in turn, chosen as the
 * "root" of the calculation and routes to all of the other routers are
 * eventually saved in the routing tables of each of the chosen nodes.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set.  The "this" SPFVertex is the vertex that
 * represents the host or network to which a route is being calculated from
 * the root.  The IP address that we're asking for is the address on the
 * remote side of a link off of the root node that should be used as the
 * destination for packets along the path to "this" vertex.
 *
 * When initializing the root SPFVertex, the IP address used when forwarding
 * packets is determined by examining the Global Router Link Records of the
 * Link State Advertisement generated by the root node's GlobalRouter.  This
 * address is used to forward packets off of the root's network down those
 * links.  As other vertices / nodes are discovered which are further away
 * from the root, they will be accessible down one of the paths via a link
 * described by one of these Global Router Link Records.
 *
 * To forward packets to these hosts or networks, the root node must begin
 * the forwarding process by sending the packets to a first hop router down
 * an interface.  This means that the first hop address and interface ID must
 * be the same for all downstream SPFVertices.  We call this "inheriting"
 * the interface and next hop.
 *
 * In this method we are telling the root node which exit direction it should send
 * should I send a packet to the network or host represented by 'this' SPFVertex.
 *
 * @see GlobalRouter
 * @see GlobalRoutingLSA
 * @see GlobalRoutingLinkRecord
 * @param exit The pair of next-hop-IP and outgoing-interface-index to use when
 * forwarding packets to the host or network represented by "this" SPFVertex.
 */
  void SetRootExitDirection (SPFVertex::NodeExit_t exit);
  /**
   * \brief Obtain a pair indicating the exit direction from the root
   *
   * \param i An index to a pair
   * \return A pair of next-hop-IP and outgoing-interface-index for
   * indicating an exit direction from the root. It is 0 if the index 'i'
   * is out-of-range
   */
  NodeExit_t GetRootExitDirection (uint32_t i) const;
  /**
   * \brief Obtain a pair indicating the exit direction from the root
   *
   * This method assumes there is only a single exit direction from the root.
   * Error occur if this assumption is invalid.
   *
   * \return The pair of next-hop-IP and outgoing-interface-index for reaching
   * 'this' vertex from the root
   */
  NodeExit_t GetRootExitDirection () const;
  /**
   * \brief Merge into 'this' vertex the list of exit directions from
   * another vertex
   *
   * This merge is necessary when ECMP are found.
   *
   * \param vertex From which the list of exit directions are obtain
   * and are merged into 'this' vertex
   */
  void MergeRootExitDirections (const SPFVertex* vertex);
  /**
   * \brief Inherit all root exit directions from a given vertex to 'this' vertex
   * \param vertex The vertex from which all root exit directions are to be inherited
   *
   * After the call of this method, the original root exit directions
   * in 'this' vertex are all lost.
   */
  void InheritAllRootExitDirections (const SPFVertex* vertex);
  /**
   * \brief Get the number of exit directions from root for reaching 'this' vertex
   * \return The number of exit directions from root
   */
  uint32_t GetNRootExitDirections () const;

/**
 * @brief Get a pointer to the SPFVector that is the parent of "this"
 * SPFVertex.
 * @internal
 *
 * Each router node in the simulation is associated with an SPFVertex object.
 * When calculating routes, each of these routers is, in turn, chosen as the
 * "root" of the calculation and routes to all of the other routers are
 * eventually saved in the routing tables of each of the chosen nodes.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set and is the root of the SPF tree.
 *
 * This method returns a pointer to the parent node of "this" SPFVertex
 * (both of which reside in that SPF tree).
 *
 * @param i The index to one of the parents
 * @returns A pointer to the SPFVertex that is the parent of "this" SPFVertex
 * in the SPF tree.
 */
  SPFVertex* GetParent (uint32_t i = 0) const;

/**
 * @brief Set the pointer to the SPFVector that is the parent of "this"
 * SPFVertex.
 * @internal
 *
 * Each router node in the simulation is associated with an SPFVertex object.
 * When calculating routes, each of these routers is, in turn, chosen as the
 * "root" of the calculation and routes to all of the other routers are
 * eventually saved in the routing tables of each of the chosen nodes.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set and is the root of the SPF tree.
 *
 * This method sets the parent pointer of "this" SPFVertex (both of which
 * reside in that SPF tree).
 *
 * @param parent A pointer to the SPFVertex that is the parent of "this"
 * SPFVertex* in the SPF tree.
 */
  void SetParent (SPFVertex* parent);
  /**
   * \brief Merge the Parent list from the v into this vertex
   *
   * \param v The vertex from which its list of Parent is read
   * and then merged into the list of Parent of *this* vertex.
   * Note that the list in v remains intact
   */
  void MergeParent (const SPFVertex* v);

/**
 * @brief Get the number of children of "this" SPFVertex.
 * @internal
 *
 * Each router node in the simulation is associated with an SPFVertex object.
 * When calculating routes, each of these routers is, in turn, chosen as the
 * "root" of the calculation and routes to all of the other routers are
 * eventually saved in the routing tables of each of the chosen nodes.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set and is the root of the SPF tree.  Each vertex
 * in the SPF tree can have a number of children that represent host or
 * network routes available via that vertex.
 *
 * This method returns the number of children of "this" SPFVertex (which
 * reside in the SPF tree).
 *
 * @returns The number of children of "this" SPFVertex (which reside in the
 * SPF tree).
 */
  uint32_t GetNChildren (void) const;

/**
 * @brief Get a borrowed SPFVertex pointer to the specified child of "this"
 * SPFVertex.
 * @internal
 *
 * Each router node in the simulation is associated with an SPFVertex object.
 * When calculating routes, each of these routers is, in turn, chosen as the
 * "root" of the calculation and routes to all of the other routers are
 * eventually saved in the routing tables of each of the chosen nodes.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set and is the root of the SPF tree.  Each vertex
 * in the SPF tree can have a number of children that represent host or
 * network routes available via that vertex.
 *
 * This method the number of children of "this" SPFVertex (which reside in
 * the SPF tree.
 *
 * @see SPFVertex::GetNChildren
 * @param n The index (from 0 to the number of children minus 1) of the
 * child SPFVertex to return.
 * @warning The pointer returned by GetChild () is a borrowed pointer.  You
 * do not have any ownership of the underlying object and must not delete
 * that object.
 * @returns A pointer to the specified child SPFVertex (which resides in the
 * SPF tree).
 */
  SPFVertex* GetChild (uint32_t n) const;

/**
 * @brief Get a borrowed SPFVertex pointer to the specified child of "this"
 * SPFVertex.
 * @internal
 *
 * Each router node in the simulation is associated with an SPFVertex object.
 * When calculating routes, each of these routers is, in turn, chosen as the
 * "root" of the calculation and routes to all of the other routers are
 * eventually saved in the routing tables of each of the chosen nodes.
 *
 * The "Root" vertex is then the SPFVertex representing the router that is
 * having its routing tables set and is the root of the SPF tree.  Each vertex
 * in the SPF tree can have a number of children that represent host or
 * network routes available via that vertex.
 *
 * This method the number of children of "this" SPFVertex (which reside in
 * the SPF tree.
 *
 * @see SPFVertex::GetNChildren
 * @warning Ownership of the pointer added to the children of "this"
 * SPFVertex is transferred to the "this" SPFVertex.  You must not delete the
 * (now) child SPFVertex after calling this method.
 * @param child A pointer to the SPFVertex (which resides in the SPF tree) to
 * be added to the list of children of "this" SPFVertex.
 * @returns The number of children of "this" SPFVertex after the addition of
 * the new child.
 */
  uint32_t AddChild (SPFVertex* child);

  /**
   * @brief Set the value of the VertexProcessed flag
   *
   * Flag to note whether vertex has been processed in stage two of
   * SPF computation
   * @param value boolean value to set the flag
   */
  void SetVertexProcessed (bool value);

  /**
   * @brief Check the value of the VertexProcessed flag
   *
   * Flag to note whether vertex has been processed in stage two of
   * SPF computation
   * @returns value of underlying flag
   */
  bool IsVertexProcessed (void) const;

  /**
   * @brief Clear the value of the VertexProcessed flag
   *
   * Flag to note whether vertex has been processed in stage two of
   * SPF computation
   */
  void ClearVertexProcessed (void);

private:
  VertexType m_vertexType; //!< Vertex type
  Ipv4Address m_vertexId; //!< Vertex ID
  GlobalRoutingLSA* m_lsa; //!< Link State Advertisement
  uint32_t m_distanceFromRoot; //!< Distance from root node
  int32_t m_rootOif; //!< root Output Interface
  Ipv4Address m_nextHop; //!< next hop
  typedef std::list< NodeExit_t > ListOfNodeExit_t; //!< container of Exit nodes
  ListOfNodeExit_t m_ecmpRootExits; //!< store the multiple root's exits for supporting ECMP
  typedef std::list<SPFVertex*> ListOfSPFVertex_t; //!< container of SPFVertexes
  ListOfSPFVertex_t m_parents; //!< parent list
  ListOfSPFVertex_t m_children; //!< Children list
  bool m_vertexProcessed; //!< Flag to note whether vertex has been processed in stage two of SPF computation

/**
 * @brief The SPFVertex copy construction is disallowed.  There's no need for
 * it and a compiler provided shallow copy would be wrong.
 */
  SPFVertex (SPFVertex& v);

/**
 * @brief The SPFVertex copy assignment operator is disallowed.  There's no
 * need for it and a compiler provided shallow copy would be wrong.
 */
  SPFVertex& operator= (SPFVertex& v);

  /**
   * \brief Stream insertion operator.
   *
   * \param os the reference to the output stream
   * \param vs a list of SPFVertexes
   * \returns the reference to the output stream
   */
  friend std::ostream& operator<< (std::ostream& os, const SPFVertex::ListOfSPFVertex_t& vs);
};

/**
 * @brief The Link State DataBase (LSDB) of the Global Route Manager.
 *
 * Each node in the simulation participating in global routing has a
 * GlobalRouter interface.  The primary job of this interface is to export
 * Global Router Link State Advertisements (LSAs).  These advertisements in
 * turn contain a number of Global Router Link Records that describe the
 * point to point links from the underlying node to other nodes (that will
 * also export their own LSAs.
 *
 * This class implements a searchable database of LSAs gathered from every
 * router in the simulation.
 */
class GlobalRouteManagerLSDB
{
public:
/**
 * @brief Construct an empty Global Router Manager Link State Database.
 * @internal
 *
 * The database map composing the Link State Database is initialized in
 * this constructor.
 */
  GlobalRouteManagerLSDB ();

/**
 * @brief Destroy an empty Global Router Manager Link State Database.
 * @internal
 *
 * The database map is walked and all of the Link State Advertisements stored
 * in the database are freed; then the database map itself is clear ()ed to
 * release any remaining resources.
 */
  ~GlobalRouteManagerLSDB ();

/**
 * @brief Insert an IP address / Link State Advertisement pair into the Link
 * State Database.
 * @internal
 *
 * The IPV4 address and the GlobalRoutingLSA given as parameters are converted
 * to an STL pair and are inserted into the database map.
 *
 * @see GlobalRoutingLSA
 * @see Ipv4Address
 * @param addr The IP address associated with the LSA.  Typically the Router
 * ID.
 * @param lsa A pointer to the Link State Advertisement for the router.
 */
  void Insert (Ipv4Address addr, GlobalRoutingLSA* lsa);

/**
 * @brief Look up the Link State Advertisement associated with the given
 * link state ID (address).
 * @internal
 *
 * The database map is searched for the given IPV4 address and corresponding
 * GlobalRoutingLSA is returned.
 *
 * @see GlobalRoutingLSA
 * @see Ipv4Address
 * @param addr The IP address associated with the LSA.  Typically the Router
 * ID.
 * @returns A pointer to the Link State Advertisement for the router specified
 * by the IP address addr.
 */
  GlobalRoutingLSA* GetLSA (Ipv4Address addr) const;
/**
 * @brief Look up the Link State Advertisement associated with the given
 * link state ID (address).  This is a variation of the GetLSA call
 * to allow the LSA to be found by matching addr with the LinkData field
 * of the TransitNetwork link record.
 * @internal
 *
 * @see GetLSA
 * @param addr The IP address associated with the LSA.  Typically the Router
 * @returns A pointer to the Link State Advertisement for the router specified
 * by the IP address addr.
 * ID.
 */
  GlobalRoutingLSA* GetLSAByLinkData (Ipv4Address addr) const;

/**
 * @brief Set all LSA flags to an initialized state, for SPF computation
 * @internal
 *
 * This function walks the database and resets the status flags of all of the
 * contained Link State Advertisements to LSA_SPF_NOT_EXPLORED.  This is done
 * prior to each SPF calculation to reset the state of the SPFVertex structures
 * that will reference the LSAs during the calculation.
 *
 * @see GlobalRoutingLSA
 * @see SPFVertex
 */
  void Initialize ();

  /**
   * @brief Look up the External Link State Advertisement associated with the given
   * index.
   * @internal
   *
   * The external database map is searched for the given index and corresponding
   * GlobalRoutingLSA is returned.
   *
   * @see GlobalRoutingLSA
   * @param index the index associated with the LSA.
   * @returns A pointer to the Link State Advertisement.
   */
  GlobalRoutingLSA* GetExtLSA (uint32_t index) const;
  /**
   * @brief Get the number of External Link State Advertisements.
   * @internal
   *
   * @see GlobalRoutingLSA
   * @returns the number of External Link State Advertisements.
   */
  uint32_t GetNumExtLSAs () const;

private:
  typedef std::map<Ipv4Address, GlobalRoutingLSA*> LSDBMap_t; //!< container of IPv4 addresses / Link State Advertisements
  typedef std::pair<Ipv4Address, GlobalRoutingLSA*> LSDBPair_t; //!< pair of IPv4 addresses / Link State Advertisements

  LSDBMap_t m_database; //!< database of IPv4 addresses / Link State Advertisements
  std::vector<GlobalRoutingLSA*> m_extdatabase; //!< database of External Link State Advertisements

/**
 * @brief GlobalRouteManagerLSDB copy construction is disallowed.  There's no
 * need for it and a compiler provided shallow copy would be wrong.
 */
  GlobalRouteManagerLSDB (GlobalRouteManagerLSDB& lsdb);

/**
 * @brief The SPFVertex copy assignment operator is disallowed.  There's no
 * need for it and a compiler provided shallow copy would be wrong.
 */
  GlobalRouteManagerLSDB& operator= (GlobalRouteManagerLSDB& lsdb);
};

/**
 * @brief A global router implementation.
 *
 * This singleton object can query interface each node in the system
 * for a GlobalRouter interface.  For those nodes, it fetches one or
 * more Link State Advertisements and stores them in a local database.
 * Then, it can compute shortest paths on a per-node basis to all routers,
 * and finally configure each of the node's forwarding tables.
 *
 * The design is guided by OSPFv2 \RFC{2328} section 16.1.1 and quagga ospfd.
 */
class GlobalRouteManagerImpl
{
public:
  GlobalRouteManagerImpl ();
  virtual ~GlobalRouteManagerImpl ();
/**
 * @brief Delete all static routes on all nodes that have a
 * GlobalRouterInterface
 *
 * \todo  separate manually assigned static routes from static routes that
 * the global routing code injects, and only delete the latter
 * @internal
 *
 */
  virtual void DeleteGlobalRoutes ();

/**
 * @brief Build the routing database by gathering Link State Advertisements
 * from each node exporting a GlobalRouter interface.
 * @internal
 */
  virtual void BuildGlobalRoutingDatabase ();

/**
 * @brief Compute routes using a Dijkstra SPF computation and populate
 * per-node forwarding tables
 * @internal
 */
  virtual void InitializeRoutes ();

/**
 * @brief Debugging routine; allow client code to supply a pre-built LSDB
 * @internal
 */
  void DebugUseLsdb (GlobalRouteManagerLSDB*);

/**
 * @brief Debugging routine; call the core SPF from the unit tests
 * @internal
 * @param root the root node to start calculations
 */
  void DebugSPFCalculate (Ipv4Address root);

private:
/**
 * @brief GlobalRouteManagerImpl copy construction is disallowed.
 * There's no  need for it and a compiler provided shallow copy would be
 * wrong.
 */
  GlobalRouteManagerImpl (GlobalRouteManagerImpl& srmi);

/**
 * @brief Global Route Manager Implementation assignment operator is
 * disallowed.  There's no  need for it and a compiler provided shallow copy
 * would be hopelessly wrong.
 */
  GlobalRouteManagerImpl& operator= (GlobalRouteManagerImpl& srmi);

  SPFVertex* m_spfroot; //!< the root node
  GlobalRouteManagerLSDB* m_lsdb; //!< the Link State DataBase (LSDB) of the Global Route Manager

  /**
   * \brief Test if a node is a stub, from an OSPF sense.
   *
   * If there is only one link of type 1 or 2, then a default route
   * can safely be added to the next-hop router and SPF does not need
   * to be run
   *
   * \param root the root node
   * \returns true if the node is a stub
   */
  bool CheckForStubNode (Ipv4Address root);

  /**
   * \brief Calculate the shortest path first (SPF) tree
   *
   * Equivalent to quagga ospf_spf_calculate
   * \param root the root node
   */
  void SPFCalculate (Ipv4Address root);

  /**
   * \brief Process Stub nodes
   *
   * Processing logic from RFC 2328, page 166 and quagga ospf_spf_process_stubs ()
   * stub link records will exist for point-to-point interfaces and for
   * broadcast interfaces for which no neighboring router can be found
   *
   * \param v vertex to be processed
   */
  void SPFProcessStubs (SPFVertex* v);

  /**
   * \brief Process Autonomous Systems (AS) External LSA
   *
   * \param v vertex to be processed
   * \param extlsa external LSA
   */
  void ProcessASExternals (SPFVertex* v, GlobalRoutingLSA* extlsa);

  /**
   * \brief Examine the links in v's LSA and update the list of candidates with any
   *        vertices not already on the list
   *
   * \internal
   *
   * This method is derived from quagga ospf_spf_next ().  See RFC2328 Section
   * 16.1 (2) for further details.
   *
   * We're passed a parameter \a v that is a vertex which is already in the SPF
   * tree.  A vertex represents a router node.  We also get a reference to the
   * SPF candidate queue, which is a priority queue containing the shortest paths
   * to the networks we know about.
   *
   * We examine the links in v's LSA and update the list of candidates with any
   * vertices not already on the list.  If a lower-cost path is found to a
   * vertex already on the candidate list, store the new (lower) cost.
   *
   * \param v the vertex
   * \param candidate the SPF candidate queue
   */
  void SPFNext (SPFVertex* v, CandidateQueue& candidate);

  /**
   * \brief Calculate nexthop from root through V (parent) to vertex W (destination)
   *        with given distance from root->W.
   *
   * This method is derived from quagga ospf_nexthop_calculation() 16.1.1.
   * For now, this is greatly simplified from the quagga code
   *
   * \param v the parent
   * \param w the destination
   * \param l the link record
   * \param distance the target distance
   * \returns 1 on success
   */
  int SPFNexthopCalculation (SPFVertex* v, SPFVertex* w,
                             GlobalRoutingLinkRecord* l, uint32_t distance);

  /**
   * \brief Adds a vertex to the list of children *in* each of its parents
   *
   * Derived from quagga ospf_vertex_add_parents ()
   *
   * This is a somewhat oddly named method (blame quagga).  Although you might
   * expect it to add a parent *to* something, it actually adds a vertex
   * to the list of children *in* each of its parents.
   *
   * Given a pointer to a vertex, it links back to the vertex's parent that it
   * already has set and adds itself to that vertex's list of children.
   *
   * \param v the vertex
   */
  void SPFVertexAddParent (SPFVertex* v);

  /**
   * \brief Search for a link between two vertexes.
   *
   * This method is derived from quagga ospf_get_next_link ()
   *
   * First search the Global Router Link Records of vertex \a v for one
   * representing a point-to point link to vertex \a w.
   *
   * What is done depends on prev_link.  Contrary to appearances, prev_link just
   * acts as a flag here.  If prev_link is NULL, we return the first Global
   * Router Link Record we find that describes a point-to-point link from \a v
   * to \a w.  If prev_link is not NULL, we return a Global Router Link Record
   * representing a possible *second* link from \a v to \a w.
   *
   * \param v first vertex
   * \param w second vertex
   * \param prev_link the previous link in the list
   * \returns the link's record
   */
  GlobalRoutingLinkRecord* SPFGetNextLink (SPFVertex* v, SPFVertex* w,
                                           GlobalRoutingLinkRecord* prev_link);

  /**
   * \brief Add a host route to the routing tables
   *
   *
   * This method is derived from quagga ospf_intra_add_router ()
   *
   * This is where we are actually going to add the host routes to the routing
   * tables of the individual nodes.
   *
   * The vertex passed as a parameter has just been added to the SPF tree.
   * This vertex must have a valid m_root_oid, corresponding to the outgoing
   * interface on the root router of the tree that is the first hop on the path
   * to the vertex.  The vertex must also have a next hop address, corresponding
   * to the next hop on the path to the vertex.  The vertex has an m_lsa field
   * that has some number of link records.  For each point to point link record,
   * the m_linkData is the local IP address of the link.  This corresponds to
   * a destination IP address, reachable from the root, to which we add a host
   * route.
   *
   * \param v the vertex
   *
   */
  void SPFIntraAddRouter (SPFVertex* v);

  /**
   * \brief Add a transit to the routing tables
   *
   * \param v the vertex
   */
  void SPFIntraAddTransit (SPFVertex* v);

  /**
   * \brief Add a stub to the routing tables
   *
   * \param l the global routing link record
   * \param v the vertex
   */
  void SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v);

  /**
   * \brief Add an external route to the routing tables
   *
   * \param extlsa the external LSA
   * \param v the vertex
   */
  void SPFAddASExternal (GlobalRoutingLSA *extlsa, SPFVertex *v);

  /**
   * \brief Return the interface number corresponding to a given IP address and mask
   *
   * This is a wrapper around GetInterfaceForPrefix(), but we first
   * have to find the right node pointer to pass to that function.
   * If no such interface is found, return -1 (note:  unit test framework
   * for routing assumes -1 to be a legal return value)
   *
   * \param a the target IP address
   * \param amask the target subnet mask
   * \return the outgoing interface number
   */
  int32_t FindOutgoingInterfaceId (Ipv4Address a,
                                   Ipv4Mask amask = Ipv4Mask ("255.255.255.255"));
};

} // namespace ns3

#endif /* GLOBAL_ROUTE_MANAGER_IMPL_H */


text:
using System;
using System.Collections.Generic;
using System.Text;

namespace TraversTree
{
    class Tree
    {
        public int Data { get; set; }
        public Tree Left { get; set; }
        public Tree Right { get; set; }

        public Tree(int data)
        {
            Data = data;
            Left = null;
            Right = null;
        }

        public void Travers()
        {
            if(Left != null)
            {
                Left.Travers();
            }
            Console.Write(Data);
            if(Right != null)
            {
                Right.Travers();
            }
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
#!/bin/bash
#
# Copyright 2016 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# An end-to-end test that Bazel's UI produces reasonable output.

# --- begin runfiles.bash initialization ---
set -euo pipefail
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
  if [[ -f "$0.runfiles_manifest" ]]; then
    export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
  elif [[ -f "$0.runfiles/MANIFEST" ]]; then
    export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
  elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
    export RUNFILES_DIR="$0.runfiles"
  fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
  source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
  source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
            "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
  echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
  exit 1
fi
# --- end runfiles.bash initialization ---

source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
  || { echo "integration_test_setup.sh not found!" >&2; exit 1; }

case "$(uname -s | tr [:upper:] [:lower:])" in
msys*|mingw*|cygwin*)
  declare -r is_windows=true
  ;;
*)
  declare -r is_windows=false
  ;;
esac

if "$is_windows"; then
  export MSYS_NO_PATHCONV=1
  export MSYS2_ARG_CONV_EXCL="*"
fi

#### SETUP #############################################################

add_to_bazelrc "build --genrule_strategy=local"
add_to_bazelrc "test --test_strategy=standalone"

function set_up() {
  if [[ -d pkg ]]; then
    # All tests share these scratch packages. No need to recreate them if they
    # already exist.
    return
  fi

  mkdir -p pkg
  touch remote_file
  cat > pkg/true.sh <<EOF
#!/bin/sh
exit 0
EOF
  chmod 755 pkg/true.sh
  cat > pkg/slow.sh <<EOF
#!/bin/sh
sleep 3
exit 0
EOF
  chmod 755 pkg/slow.sh
  cat > pkg/false.sh <<EOF
#!/bin/sh
exit 1
EOF
  chmod 755 pkg/false.sh
  cat > pkg/output.sh <<EOF
#!/bin/sh
`which echo` -n foo
sleep 1
`which echo` -n bar
exit 0
EOF
  chmod 755 pkg/output.sh
  cat > pkg/do_output.sh <<EOF
#!/bin/sh
echo Beginning \$1
for _ in \`seq 1 10240\`
do echo '1234567890'
done
echo Ending \$1
EOF
  chmod 755 pkg/do_output.sh
  cat > pkg/BUILD <<EOF
sh_test(
  name = "true",
  srcs = ["true.sh"],
)
sh_test(
  name = "slow",
  srcs = ["slow.sh"],
)
sh_test(
  name = "false",
  srcs = ["false.sh"],
)
sh_test(
  name = "output",
  srcs = ["output.sh"],
)
genrule(
  name = "gentext",
  outs = ["gentext.txt"],
  cmd = "echo here be dragons > \"\$@\""
)
genrule(
  name = "withOutputA",
  outs = ["a"],
  tools = [":do_output.sh"],
  cmd = "\$(location :do_output.sh) A && touch \"\$@\"",
)
genrule(
  name = "withOutputB",
  outs = ["b"],
  tools = [":do_output.sh"],
  cmd = "\$(location :do_output.sh) B && touch \$@",
)
sh_library(
  name = "outputlib",
  data = [":withOutputA", ":withOutputB"],
)
sh_test(
  name = "truedependingonoutput",
  srcs = ["true.sh"],
  deps = [":outputlib"],
)
EOF
  mkdir -p error
  cat > error/BUILD <<'EOF'
genrule(
  name = "failwitherror",
  outs = ["fail.txt"],
  cmd = "echo Here is the error message; exit 1",
)
EOF
  mkdir -p pkg/errorAfterWarning
  cat > pkg/errorAfterWarning/BUILD <<'EOF'
RANGE = range(500)

[ genrule(
    name = "true%s_c" % i,
    outs = ["true%s.c" % i],
    cmd = "echo Build Warning...; echo 'int main(int argc, char **argv) { return 0; }' > $@",
) for i in RANGE]

[ cc_binary(
    name = "true_%s" % i,
    srcs = ["true%s.c" % i],
) for i in RANGE]

genrule(
  name = "failing",
  outs = ["failing.txt"],
  srcs = ["true_%s" % i for i in RANGE],
  cmd = "echo This is the error message; false",
)
EOF
  chmod -w pkg/* # prevent accidental editing
  # keep directories writable though, so that test clean up can work
  chmod 755 error
  chmod 755 pkg/errorAfterWarning
  mkdir -p pkg/debugMessages
  cat > pkg/debugMessages/rule.bzl <<'EOF'
def _impl(ctx):
  print("static debug message")
  ctx.actions.write(ctx.outputs.out, "Hello World")

withdebug = rule(
  implementation = _impl,
  attrs = {},
  outputs = {"out" : "%{name}.txt"},
)
EOF
  cat > pkg/debugMessages/BUILD <<'EOF'
load("//pkg/debugMessages:rule.bzl", "withdebug")

[ withdebug(name = "target%d" % (i,)) for i in range(50) ]
EOF
  mkdir -p bzl
  touch bzl/BUILD
  cat > bzl/bzl.bzl <<'EOF'
x = invalidsyntax
EOF
  mkdir -p pkgloadingerror
  cat > pkgloadingerror/BUILD <<'EOF'
load("//bzl:bzl.bzl", "x")
EOF
  mkdir -p fancyOutput
  cat > fancyOutput/BUILD <<'EOF'
genrule(
  name = "withFancyOutput",
  outs = ["out.txt"],
  cmd = "echo $$'\\xF0\\x9F\\x8D\\x83'; echo Hello World > $@",
)
EOF
}

function create_pkg() {
  local -r pkg=$1
  mkdir -p $pkg
  cat > $pkg/true.sh <<EOF
#!/bin/sh
exit 0
EOF
  chmod 755 $pkg/true.sh
  cat > $pkg/BUILD <<EOF
sh_test(
  name = "true",
  srcs = ["true.sh"],
)
EOF
}

#### TESTS #############################################################

function test_basic_progress() {
  bazel test --curses=yes --color=yes pkg:true 2>$TEST_log \
    || fail "${PRODUCT_NAME} test failed"
  # some progress indicator is shown
  expect_log '\[[0-9,]* / [0-9,]*\]'
  # curses are used to delete at least one line
  expect_log $'\x1b\[1A\x1b\[K'
  # As precisely one target is specified, it should be reported during
  # analysis phase.
  expect_log 'Analy.*pkg:true'
}

function test_line_wrapping() {
  local -r pkg=$FUNCNAME
  create_pkg $pkg
  bazel test --curses=yes --color=yes --terminal_columns=5 $pkg:true 2>$TEST_log || fail "bazel test failed"
  # curses are used to delete at least one line
  expect_log $'\x1b\[1A\x1b\[K'
  # something is written in green
  expect_log $'\x1b\[32m'
  # lines are wrapped, hence at least one line should end with backslash
  expect_log '\\'$'\r''$\|\\$'
}

function test_noshow_progress() {
  bazel test --noshow_progress --curses=yes --color=yes \
    pkg:true 2>$TEST_log || fail "${PRODUCT_NAME} test failed"
  # Info messages should still go through
  expect_log 'Elapsed time'
  # no progress indicator is shown
  expect_not_log '\[[0-9,]* / [0-9,]*\]'
}

function test_basic_progress_no_curses() {
  bazel test --curses=no --color=yes pkg:true 2>$TEST_log \
    || fail "${PRODUCT_NAME} test failed"
  # some progress indicator is shown
  expect_log '\[[0-9,]* / [0-9,]*\]'
  # cursor is not moved up
  expect_not_log $'\x1b\[1A'
  # no line is deleted
  expect_not_log $'\x1b\[K'
  # but some green color is used
  expect_log $'\x1b\[32m'
}

function test_no_curses_no_linebreak() {
  bazel test --curses=no --color=yes --terminal_columns=9 \
    pkg:true 2>$TEST_log || fail "${PRODUCT_NAME} test failed"
  # expect a long-ish status line
  expect_log '\[[0-9,]* / [0-9,]*\]......'
}

function test_pass() {
  bazel test --curses=yes --color=yes pkg:true >$TEST_log \
    || fail "${PRODUCT_NAME} test failed"
  # PASS is written in green on the same line as the test target
  expect_log 'pkg:true.*'$'\x1b\[32m''.*PASS'
}

function test_fail() {
  bazel test --curses=yes --color=yes pkg:false >$TEST_log \
    && fail "expected failure"
  # FAIL is written in red bold on the same line as the test target
  expect_log 'pkg:false.*'$'\x1b\[31m\x1b\[1m''.*FAIL'
}

function test_timestamp() {
  bazel test --show_timestamps pkg:true 2>$TEST_log \
    || fail "${PRODUCT_NAME} test failed"
  # expect something that looks like HH:mm:ss
  expect_log '[0-2][0-9]:[0-5][0-9]:[0-6][0-9]'
}

function test_skymeld_ui() {
  bazel build --experimental_skymeld_ui pkg:true &> "$TEST_log" \
    || fail "${PRODUCT_NAME} test failed."
  expect_log 'Build completed successfully'
}

# Regression test for b/244163231.
function test_skymeld_ui_with_starlark_flags() {
  local -r pkg=$FUNCNAME
  create_pkg $pkg
  mkdir -p "${pkg}/flags"

  cat > "${pkg}/flags/flags.bzl" <<EOF
def _impl(ctx):
  pass

string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True),
)
EOF

  cat > "${pkg}/flags/BUILD" <<EOF
load('//${pkg}/flags:flags.bzl', 'string_flag')

string_flag(
    name = "flag",
    build_setting_default = "a",
)
EOF

  bazel build --experimental_skymeld_ui \
      --//$pkg/flags:flag=a \
      $pkg:true &> "$TEST_log" || fail "${PRODUCT_NAME} test failed."
  expect_log 'Build completed successfully'
}

# Regression test for b/244163231.
function test_skymeld_ui_works_with_timestamps() {
  bazel build --experimental_skymeld_ui --show_timestamps \
    pkg:true &> "$TEST_log" \
    || fail "${PRODUCT_NAME} test failed."
  expect_log 'Build completed successfully'
}

function test_info_spacing() {
  # Verify that the output of "bazel info" is suitable for backtick escapes,
  # in particular free carriage-return characters.
  BAZEL_INFO_OUTPUT=XXX`bazel info workspace`XXX
  echo "$BAZEL_INFO_OUTPUT" | grep -q 'XXX[^'$'\r'']*XXX' \
    || fail "${PRODUCT_NAME} info output spaced as $BAZEL_INFO_OUTPUT"
}

function test_query_spacing() {
  # Verify that the output of "bazel query" is suitable for consumption by
  # other tools, i.e., contains only result lines, separated only by newlines.
  BAZEL_QUERY_OUTPUT=`bazel query 'deps(//pkg:true)'`
  echo "$BAZEL_QUERY_OUTPUT" | grep -q -v '^[@/]' \
   && fail "bazel query output is >$BAZEL_QUERY_OUTPUT<" || true
  if ! $is_windows; then
    echo "$BAZEL_QUERY_OUTPUT" | grep -q $'\r' \
     && fail "bazel query output is >$BAZEL_QUERY_OUTPUT<" || true
  fi
}

function test_query_progress() {
  # Verify that some form of progress is reported during bazel query
  bazel query 'deps(//pkg:true)' 2> "${TEST_log}"
  expect_log 'Loading:.*packages loaded'
}

function test_clean_nobuild {
  bazel clean 2>$TEST_log \
   || fail "bazel shutdown failed"
  expect_not_log "actions running"
  expect_not_log "Building"
}

function test_clean_color_nobuild {
  bazel clean --color=yes 2>$TEST_log \
   || fail "bazel shutdown failed"
  expect_not_log "actions running"
  expect_not_log "Building"
}

function test_help_nobuild {
  bazel help 2>$TEST_log \
   || fail "bazel help failed"
  expect_not_log "actions running"
  expect_not_log "Building"
}

function test_help_color_nobuild {
  bazel help --color=yes 2>$TEST_log \
   || fail "bazel help failed"
  expect_not_log "actions running"
  expect_not_log "Building"
}

function test_version_nobuild {
  bazel version --curses=yes 2>$TEST_log \
   || fail "bazel version failed"
  expect_not_log "action"
  expect_not_log "Building"
}

function test_version_nobuild_announce_rc {
  bazel version --curses=yes --announce_rc 2>$TEST_log \
   || fail "bazel version failed"
  expect_not_log "action"
  expect_not_log "Building"
}

function test_subcommand {
  bazel clean || fail "${PRODUCT_NAME} clean failed"
  bazel build -s pkg:gentext 2>$TEST_log \
    || fail "bazel build failed"
  expect_log "here be dragons"
}

function test_subcommand_notdefault {
  bazel clean || fail "${PRODUCT_NAME} clean failed"
  bazel build pkg:gentext 2>$TEST_log \
    || fail "bazel build failed"
  expect_not_log "dragons"
}

function test_loading_progress {
  bazel clean || fail "${PRODUCT_NAME} clean failed"
  bazel test pkg:true 2>$TEST_log \
    || fail "${PRODUCT_NAME} test failed"
  # some progress indicator is shown during loading
  expect_log 'Loading.*[0-9,]* packages'
}

function test_failure_scrollback_buffer_curses {
  bazel clean || fail "${PRODUCT_NAME} clean failed"
  bazel test --curses=yes --color=yes \
    --nocache_test_results pkg:false pkg:slow 2>$TEST_log \
    && fail "expected failure"
  # Some line starts with FAIL in red bold.
  expect_log '^'$'\(.*\x1b\[K\)*\x1b\[31m\x1b\[1mFAIL:'
}

function test_terminal_title {
  bazel test --curses=yes \
    --progress_in_terminal_title pkg:true \
    2>$TEST_log || fail "${PRODUCT_NAME} test failed"
  # The terminal title is changed
  expect_log $'\x1b\]0;.*\x07'
}

function test_failure_scrollback_buffer {
  bazel clean || fail "${PRODUCT_NAME} clean failed"
  bazel test --curses=no --color=yes \
    --nocache_test_results pkg:false pkg:slow 2>$TEST_log \
    && fail "expected failure"
  # Some line starts with FAIL in red bold.
  expect_log '^'$'\x1b\[31m\x1b\[1mFAIL:'
}

function test_streamed {
  bazel test --curses=yes --color=yes \
    --nocache_test_results --test_output=streamed pkg:output >$TEST_log \
    || fail "expected success"
  expect_log 'foobar'
}

function test_stdout_bundled {
    # Verify that the error message is part of the error event
    bazel build --experimental_ui_debug_all_events \
          error:failwitherror > "${TEST_log}" 2>&1 \
    && fail "expected failure" || :
    grep -A1 '^ERROR' "${TEST_log}" \
        | grep -q "with STDOUT: Here is the error message" \
        || fail "Error message not bundled"
}

function test_experimental_ui_attempt_to_print_relative_paths_failing_action() {
  # On the BazelCI Windows environment, `pwd` returns a string that uses a
  # lowercase drive letter and unix-style path separators (e.g. '/c/') with
  # a lowercase drive letter. But internally in Bazel, Path#toString
  # unconditionally uses an uppercase drive letter (see
  # WindowsOsPathPolicy#normalize). I want these tests to check for exact
  # string contents (that's the entire goal of the flag being tested), but I
  # don't want them to be brittle across different Windows enviromments, so
  # I've disabled them for now.
  # TODO(nharmata): Fix this.
  [[ "$is_windows" == "true" ]] && return 0

  bazel clean || fail "${PRODUCT_NAME} clean failed"

  bazel build --attempt_to_print_relative_paths=false \
      error:failwitherror > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_log "^ERROR: $(pwd)/error/BUILD:1:8: Executing genrule //error:failwitherror failed: "

  bazel build --attempt_to_print_relative_paths=true \
      error:failwitherror > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_log "^ERROR: error/BUILD:1:8: Executing genrule //error:failwitherror failed: "
  expect_not_log "$(pwd)/error/BUILD"
}

function test_experimental_ui_attempt_to_print_relative_paths_pkg_error() {
  # See the note in the test case above for why this is disabled on Windows.
  # TODO(nharmata): Fix this.
  [[ "$is_windows" == "true" ]] && return 0

  bazel clean || fail "${PRODUCT_NAME} clean failed"

  bazel build --attempt_to_print_relative_paths=false \
      pkgloadingerror:all > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_log "^ERROR: $(pwd)/bzl/bzl.bzl:1:5: name 'invalidsyntax' is not defined"

  bazel build --attempt_to_print_relative_paths=true \
      pkgloadingerror:all > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_log "^ERROR: bzl/bzl.bzl:1:5: name 'invalidsyntax' is not defined"
  expect_not_log "$(pwd)/bzl/bzl.bzl"
}

function test_fancy_symbol_encoding() {
    bazel build //fancyOutput:withFancyOutput > "${TEST_log}" 2>&1 \
        || fail "expected success"
    expect_log $'\xF0\x9F\x8D\x83'
}

function test_ui_events_filters() {
  bazel clean || fail "${PRODUCT_NAME} clean failed"

  bazel build pkgloadingerror:all > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_log "^ERROR: .*/bzl/bzl.bzl:1:5: name 'invalidsyntax' is not defined"
  expect_log "^WARNING: Target pattern parsing failed."
  expect_log "^INFO: Elapsed time"

  bazel build --ui_event_filters=-error pkgloadingerror:all > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_not_log "^ERROR: .*bzl/bzl.bzl:1:5: name 'invalidsyntax' is not defined"
  expect_log "^WARNING: Target pattern parsing failed."
  expect_log "^INFO: Elapsed time"

  bazel build --ui_event_filters=info pkgloadingerror:all > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_not_log "^ERROR: .*/bzl/bzl.bzl:1:5: name 'invalidsyntax' is not defined"
  expect_not_log "^WARNING: Target pattern parsing failed."
  expect_log "^INFO: Elapsed time"

  bazel build  --ui_event_filters= pkgloadingerror:all > "${TEST_log}" 2>&1 && fail "expected failure"
  expect_not_log "^ERROR: .*/bzl/bzl.bzl:1:5: name 'invalidsyntax' is not defined"
  expect_not_log "^WARNING: Target pattern parsing failed."
  expect_not_log "^INFO: Elapsed time"
}

function test_max_stdouterr_bytes_capping_behavior() {
  mkdir -p outs
  cat >outs/BUILD <<'EOF'
genrule(
  name = "short-stdout",
  outs = ["short-stdout.txt"],
  cmd = "echo 'abc'; touch $@",
)
genrule(
  name = "short-stderr",
  outs = ["short-stderr.txt"],
  cmd = "echo 'abc' 1>&2; touch $@",
)
genrule(
  name = "long-stdout",
  outs = ["long-stdout.txt"],
  cmd = "echo 'long line of text'; touch $@",
)
genrule(
  name = "long-stderr",
  outs = ["long-stderr.txt"],
  cmd = "echo 'long line of text' 1>&2; touch $@",
)
genrule(
  name = "short-stdout-long-stderr",
  outs = ["short-stdout-long-stderr.txt"],
  cmd = "echo 'abc'; echo 'long line of text' 1>&2; touch $@",
)
genrule(
  name = "long-stdout-short-stderr",
  outs = ["long-stdout-short-stderr.txt"],
  cmd = "echo 'abc' 1>&2; echo 'long line of text'; touch $@",
)
EOF

  for n in stdout stderr; do
    bazel build --experimental_ui_max_stdouterr_bytes=5 "//outs:short-$n" \
        >"${TEST_log}" 2>&1 || fail "build failed"
    expect_log 'abc'
    expect_not_log 'exceeds maximum size'

    bazel build --experimental_ui_max_stdouterr_bytes=5 "//outs:long-$n" \
        >"${TEST_log}" 2>&1 || fail "build failed"
    expect_not_log 'long line of text'
    expect_log 'exceeds maximum size'
  done

  bazel build --experimental_ui_max_stdouterr_bytes=5 \
      //outs:short-stdout-long-stderr \
      >"${TEST_log}" 2>&1 || fail "build failed"
  expect_log 'abc'
  expect_log 'stderr .*/actions/stderr-.* exceeds maximum size'

  bazel build --experimental_ui_max_stdouterr_bytes=5 \
      //outs:long-stdout-short-stderr \
      >"${TEST_log}" 2>&1 || fail "build failed"
  expect_log 'abc'
  expect_log 'stdout .*/actions/stdout-.* exceeds maximum size'
}

function test_max_stdouterr_bytes_is_for_individual_outputs() {
  mkdir -p outs
  cat >>outs/BUILD <<'EOF'
[genrule(
    name = "out-%d" % i,
    outs = [("out-%d.txt") % i],
    cmd = ("echo '>>>%d<<<'; touch $@") % i,
) for i in range(1000)]
EOF
  # Set --experimental_ui_max_stdouterr_bytes to a low-enough number that
  # tolerates a single stdout and run many concurrent jobs at once to ensure
  # that this limit applies to individual outputs even if we are trying to read
  # all files concurrently.
  bazel build --experimental_ui_max_stdouterr_bytes=20 --jobs=200 //outs/... \
      >"${TEST_log}" 2>&1 || fail "build failed"
  for i in $(seq 0 999); do
    expect_log ">>>${i}<<<"
  done
}

function test_interleaved_errors_and_progress() {
  # Background process necessary to interrupt Bazel doesn't go well on Windows.
  [[ "$is_windows" == true ]] && return
  mkdir -p foo
  cat > foo/BUILD <<'EOF'
genrule(name = 'sleep', outs = ['sleep.out'], cmd = 'sleep 10000')
genrule(name = 'fail',
        outs = ['fail.out'],
        srcs = [':multiline.sh'],
        cmd = '$(location :multiline.sh)'
)
EOF
  cat > foo/multiline.sh <<'EOF'
echo "This
is
a
multiline error message
before
failure"
false
EOF
  chmod +x foo/multiline.sh
  bazel build -k //foo:all --curses=yes >& "$TEST_log" &
  pid="$!"
  while ! grep -q "multiline error message" "$TEST_log" ; do
    sleep 1
  done
  while ! grep -q '\[2 / 3\] Executing genrule //foo:sleep' "$TEST_log" ; do
    sleep 1
  done
  kill -SIGINT "$pid"
  wait "$pid" || exit_code="$?"
  [[ "$exit_code" == 8 ]] || fail "Should have been interrupted: $exit_code"
  tr -s <"$TEST_log" '\n' '@' |
      grep -q 'Executing genrule //foo:fail failed:[^@]*@This@is@a@multiline error message@before@failure@\[2 / 3\] Executing genrule //foo:sleep;' \
      || fail "Unified genrule error message not found"
  # Make sure server is still usable.
  bazel info server_pid >& "$TEST_log" || fail "Couldn't use server"
}

function test_progress_bar_after_stderr() {
  mkdir -p foo
  cat > foo/BUILD <<'EOF'
genrule(name = 'fail', outs = ['fail.out'], cmd = 'false')
sh_test(name = 'foo', data = [':fail'], srcs = ['foo.sh'])
EOF
  touch foo/foo.sh
  chmod +x foo/foo.sh
  # Build event file needed so UI considers build to continue after failure.
  ! bazel test --build_event_json_file=bep.json --curses=yes --color=yes \
      //foo:foo &> "$TEST_log" || fail "Expected failure"
  # Expect to see a failure message with an "erase line" control code prepended.
  expect_log $'\e'"\[K"$'\e'"\[31m"$'\e'"\[1mFAILED:"$'\e'"\[0m Build did NOT complete successfully"
  # We should not see a build failure message without an "erase line" to start.
  # TODO(janakr): Fix the excessive printing of this failure message.
  expect_log_n "^"$'\e'"\[31m"$'\e'"\[1mFAILED:"$'\e'"\[0m Build did NOT complete successfully" 4
}

run_suite "Integration tests for ${PRODUCT_NAME}'s UI"


text:
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Favourite;
use Illuminate\Support\Facades\Auth;

class FavouritesController extends Controller
{
    //
    public function getAll()
    {
    	return view('favourites', [
            'favs' => Auth::user()->favourites
        ]);
    }

    public function editFavourite(Request $req)
    {
        // check if already exists
        $exists = Auth::user()
            ->favourites()
            ->where('movie_id', $req->movie_id);

        // if this user does not have this movie, add it.
        if($exists->count() == 0){

            // create a new favourite.
	    	$fav = new Favourite();

            // add attributes
	    	$fav->movie_id = $req->movie_id;
	    	$fav->movie_title = $req->movie_title;
	    	$fav->poster_path = $req->poster_path;

            Auth::user()
                ->favourites()
                ->save($fav);

            return "Added";

            // if this user has this movie, delete it.
	    } else if ($exists->count() == 1) {
            $exists->delete();
            return "Deleted";
        }

        // if for whatever reason this runs. uh oh.
        return "Error";
    }
}


text:
// This file is automatically generated.

package adila.db;

/*
 * ZTE Blade Apex2
 *
 * DEVICE: msm8226
 * MODEL: ZTE Blade Apex2
 */
final class msm8226_zte20blade20apex2 {
    public static final String DATA = "ZTE|Blade Apex2|";
}


text:
[Full Changelog](https://github.com/inaka/cowboy-trails/compare/2.2.1...2.3.0)

**Merged pull requests:**

- Remove unused dep. xref\_runner [\#103](https://github.com/inaka/cowboy-trails/pull/103) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- Remove error-prone \_meta\_SUITE while creating alias \_test\_ [\#102](https://github.com/inaka/cowboy-trails/pull/102) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- trails\_handler supports parameter [\#101](https://github.com/inaka/cowboy-trails/pull/101) ([turtleDeng](https://github.com/turtleDeng))
- Allow for analysis under rebar3\_hank [\#100](https://github.com/inaka/cowboy-trails/pull/100) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- Increase consumer confidence [\#99](https://github.com/inaka/cowboy-trails/pull/99) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- Move to a GitHub action \(instead of container-based\) CI approach [\#98](https://github.com/inaka/cowboy-trails/pull/98) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))

## [2.2.1](https://github.com/inaka/cowboy-trails/tree/2.2.1) (2021-03-25)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/2.2.0...2.2.1)

**Merged pull requests:**

- Bump some dep.s for OTP 24 compatibility [\#97](https://github.com/inaka/cowboy-trails/pull/97) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- Prevent compilation warnings on \(upcoming\) OTP 24 [\#96](https://github.com/inaka/cowboy-trails/pull/96) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))

## [2.2.0](https://github.com/inaka/cowboy-trails/tree/2.2.0) (2021-01-28)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/0.2.2...2.2.0)

**Closed issues:**

- Release request [\#94](https://github.com/inaka/cowboy-trails/issues/94)
- Reach 100% Code Coverage with Tests [\#84](https://github.com/inaka/cowboy-trails/issues/84)

**Merged pull requests:**

- Fix \#94: New release \(2.2.0\) [\#95](https://github.com/inaka/cowboy-trails/pull/95) ([elbrujohalcon](https://github.com/elbrujohalcon))
- 100% test coverage [\#93](https://github.com/inaka/cowboy-trails/pull/93) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- Prevent cowboy from breaking CI [\#92](https://github.com/inaka/cowboy-trails/pull/92) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- GitHub Actions + updated dependencies [\#91](https://github.com/inaka/cowboy-trails/pull/91) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))
- Remove rebar.config.script as it's not needed anymore [\#90](https://github.com/inaka/cowboy-trails/pull/90) ([srijan](https://github.com/srijan))

## [0.2.2](https://github.com/inaka/cowboy-trails/tree/0.2.2) (2019-02-21)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/2.1.0...0.2.2)

**Merged pull requests:**

- Fix 0.2.1 type -spec\(\).s [\#89](https://github.com/inaka/cowboy-trails/pull/89) ([paulo-ferraz-oliveira](https://github.com/paulo-ferraz-oliveira))

## [2.1.0](https://github.com/inaka/cowboy-trails/tree/2.1.0) (2018-04-30)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/2.0.0...2.1.0)

**Closed issues:**

- Update Dependencies [\#85](https://github.com/inaka/cowboy-trails/issues/85)
- trails:do\_store hangs for 60 seconds [\#82](https://github.com/inaka/cowboy-trails/issues/82)

**Merged pull requests:**

- Reapply \#83 [\#88](https://github.com/inaka/cowboy-trails/pull/88) ([elbrujohalcon](https://github.com/elbrujohalcon))
- Bump Version to 2.1.0 [\#87](https://github.com/inaka/cowboy-trails/pull/87) ([elbrujohalcon](https://github.com/elbrujohalcon))
- \[Fix \#85\] Update Dependencies [\#86](https://github.com/inaka/cowboy-trails/pull/86) ([elbrujohalcon](https://github.com/elbrujohalcon))
- \[\#82\] Don't call ensure\_all\_started from do\_store [\#83](https://github.com/inaka/cowboy-trails/pull/83) ([tothlac](https://github.com/tothlac))

## [2.0.0](https://github.com/inaka/cowboy-trails/tree/2.0.0) (2017-11-29)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/1.0.0...2.0.0)

**Closed issues:**

- compatibility with beta of cowboy 2.0x ? [\#72](https://github.com/inaka/cowboy-trails/issues/72)

**Merged pull requests:**

- Bump to 2.0.0 [\#81](https://github.com/inaka/cowboy-trails/pull/81) ([jfacorro](https://github.com/jfacorro))
- \[Closes \#72\] Update to Cowboy 2 [\#79](https://github.com/inaka/cowboy-trails/pull/79) ([jfacorro](https://github.com/jfacorro))

## [1.0.0](https://github.com/inaka/cowboy-trails/tree/1.0.0) (2017-11-29)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/0.2.1...1.0.0)

**Merged pull requests:**

- Actually move to 1.0.0 [\#80](https://github.com/inaka/cowboy-trails/pull/80) ([elbrujohalcon](https://github.com/elbrujohalcon))
- Bump version to 1.0.0 [\#78](https://github.com/inaka/cowboy-trails/pull/78) ([jfacorro](https://github.com/jfacorro))
- Remove dead hipchat link [\#77](https://github.com/inaka/cowboy-trails/pull/77) ([Euen](https://github.com/Euen))
- Remove dead hipchat link [\#76](https://github.com/inaka/cowboy-trails/pull/76) ([elbrujohalcon](https://github.com/elbrujohalcon))
- Review formatting in example [\#75](https://github.com/inaka/cowboy-trails/pull/75) ([lucafavatella](https://github.com/lucafavatella))
- Correct references to unexported type [\#74](https://github.com/inaka/cowboy-trails/pull/74) ([lucafavatella](https://github.com/lucafavatella))
- Plant CI [\#73](https://github.com/inaka/cowboy-trails/pull/73) ([lucafavatella](https://github.com/lucafavatella))

## [0.2.1](https://github.com/inaka/cowboy-trails/tree/0.2.1) (2016-10-05)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/0.2.0...0.2.1)

**Closed issues:**

- Version Bump to 0.2.1 [\#70](https://github.com/inaka/cowboy-trails/issues/70)
- Fix Hex package [\#63](https://github.com/inaka/cowboy-trails/issues/63)
- Example use unavailable dep [\#54](https://github.com/inaka/cowboy-trails/issues/54)

**Merged pull requests:**

- \[Close \#70\] version bump to 0.2.1 [\#71](https://github.com/inaka/cowboy-trails/pull/71) ([Euen](https://github.com/Euen))
- \[Close \#54\] move example from erlang.mk to rebar3 [\#69](https://github.com/inaka/cowboy-trails/pull/69) ([Euen](https://github.com/Euen))
- Minor type fixes [\#68](https://github.com/inaka/cowboy-trails/pull/68) ([HernanRivasAcosta](https://github.com/HernanRivasAcosta))

## [0.2.0](https://github.com/inaka/cowboy-trails/tree/0.2.0) (2016-08-11)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/0.1.1...0.2.0)

**Fixed bugs:**

- trails\_meta tests fails [\#60](https://github.com/inaka/cowboy-trails/pull/60) ([jeanparpaillon](https://github.com/jeanparpaillon))

**Closed issues:**

- Version Bump to 0.2.0 [\#66](https://github.com/inaka/cowboy-trails/issues/66)
- Move from erlang.mk to rebar3 [\#64](https://github.com/inaka/cowboy-trails/issues/64)
- Add a function to retrieve the list of registered servers and hostmatches [\#61](https://github.com/inaka/cowboy-trails/issues/61)
- Update repo and make it ready for hex.pm [\#57](https://github.com/inaka/cowboy-trails/issues/57)
- How to pass options? [\#56](https://github.com/inaka/cowboy-trails/issues/56)
- Switch build tools to erlang.mk and republish to hex.pm [\#53](https://github.com/inaka/cowboy-trails/issues/53)

**Merged pull requests:**

- \[Close \#66\] version bump 0.2.0 [\#67](https://github.com/inaka/cowboy-trails/pull/67) ([Euen](https://github.com/Euen))
- \[Close \#64\] move to rebar3 [\#65](https://github.com/inaka/cowboy-trails/pull/65) ([Euen](https://github.com/Euen))
- \[Fix \#61\] Add retrieval of registered servers and hostmatches [\#62](https://github.com/inaka/cowboy-trails/pull/62) ([llamallamaduck](https://github.com/llamallamaduck))
- Update rebar.config to use Hex dependencies [\#59](https://github.com/inaka/cowboy-trails/pull/59) ([waisbrot](https://github.com/waisbrot))
- \[Fix \#57\] Update dependencies; Update erlang.mk; Add ruleset to elvis config [\#58](https://github.com/inaka/cowboy-trails/pull/58) ([harenson](https://github.com/harenson))
- Make example using current code version [\#55](https://github.com/inaka/cowboy-trails/pull/55) ([jeanparpaillon](https://github.com/jeanparpaillon))

## [0.1.1](https://github.com/inaka/cowboy-trails/tree/0.1.1) (2016-01-06)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/0.1.0...0.1.1)

**Merged pull requests:**

- Hex Package [\#45](https://github.com/inaka/cowboy-trails/pull/45) ([elbrujohalcon](https://github.com/elbrujohalcon))

## [0.1.0](https://github.com/inaka/cowboy-trails/tree/0.1.0) (2015-11-26)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/0.0.2...0.1.0)

**Fixed bugs:**

- Fix trails:store spec [\#43](https://github.com/inaka/cowboy-trails/issues/43)

**Closed issues:**

- Bump version to 0.1.0 [\#49](https://github.com/inaka/cowboy-trails/issues/49)
- Add Meta Testing [\#46](https://github.com/inaka/cowboy-trails/issues/46)
- Allow the user to set a global api-root path [\#42](https://github.com/inaka/cowboy-trails/issues/42)
- Improve Example [\#27](https://github.com/inaka/cowboy-trails/issues/27)
- Allow more than one server running on the same node [\#19](https://github.com/inaka/cowboy-trails/issues/19)

**Merged pull requests:**

- \[Fix \#49\] Bump version to 0.1.0 [\#51](https://github.com/inaka/cowboy-trails/pull/51) ([harenson](https://github.com/harenson))
- \[Fix \#19\] Allow more than one server running on the same node [\#50](https://github.com/inaka/cowboy-trails/pull/50) ([harenson](https://github.com/harenson))
- \[Fix \#46\] Add meta testing [\#48](https://github.com/inaka/cowboy-trails/pull/48) ([harenson](https://github.com/harenson))
- Allow the user to set and get global api-root path [\#47](https://github.com/inaka/cowboy-trails/pull/47) ([harenson](https://github.com/harenson))
- trails:store spec fixed [\#44](https://github.com/inaka/cowboy-trails/pull/44) ([ferigis](https://github.com/ferigis))
- \[Closes \#27\] Improve example [\#41](https://github.com/inaka/cowboy-trails/pull/41) ([jfacorro](https://github.com/jfacorro))

## [0.0.2](https://github.com/inaka/cowboy-trails/tree/0.0.2) (2015-08-06)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/0.0.1...0.0.2)

**Closed issues:**

- Fulfil the open-source checklist [\#11](https://github.com/inaka/cowboy-trails/issues/11)

**Merged pull requests:**

- Version bump. [\#40](https://github.com/inaka/cowboy-trails/pull/40) ([cabol](https://github.com/cabol))
- Fixed trails:trails/1 and trails\_handler callback spec. [\#39](https://github.com/inaka/cowboy-trails/pull/39) ([cabol](https://github.com/cabol))
- Fixed metadata type, now is trails:metadata/1. [\#38](https://github.com/inaka/cowboy-trails/pull/38) ([cabol](https://github.com/cabol))

## [0.0.1](https://github.com/inaka/cowboy-trails/tree/0.0.1) (2015-07-24)

[Full Changelog](https://github.com/inaka/cowboy-trails/compare/45e660ea86d556e94116449c6794477b56b38122...0.0.1)

**Fixed bugs:**

- Ensure store/1 can receive Cowboy's  \[route\_path\(\)\] [\#29](https://github.com/inaka/cowboy-trails/issues/29)
- Ensure that the order how list of trails comes when call `trails:store/1` be the same when call `trails:all/0`. [\#28](https://github.com/inaka/cowboy-trails/issues/28)

**Closed issues:**

- Add rebar support [\#26](https://github.com/inaka/cowboy-trails/issues/26)
- Example application with Cowboy-Trails [\#24](https://github.com/inaka/cowboy-trails/issues/24)
- deps should use https not git [\#21](https://github.com/inaka/cowboy-trails/issues/21)
- Add a method field to trails [\#10](https://github.com/inaka/cowboy-trails/issues/10)
- persistence [\#9](https://github.com/inaka/cowboy-trails/issues/9)
- Add optional metadata to trail\(\). [\#8](https://github.com/inaka/cowboy-trails/issues/8)
- trails:trails/1 [\#7](https://github.com/inaka/cowboy-trails/issues/7)
- trails:trail/3,4 [\#6](https://github.com/inaka/cowboy-trails/issues/6)
- trails:single\_host\_compile [\#5](https://github.com/inaka/cowboy-trails/issues/5)
- Basic trails implementation [\#4](https://github.com/inaka/cowboy-trails/issues/4)
- Base app structure [\#3](https://github.com/inaka/cowboy-trails/issues/3)

**Merged pull requests:**

- Version Bump. [\#37](https://github.com/inaka/cowboy-trails/pull/37) ([cabol](https://github.com/cabol))
- Added edoc to describe modules. [\#36](https://github.com/inaka/cowboy-trails/pull/36) ([cabol](https://github.com/cabol))
- Fixed edoc. [\#35](https://github.com/inaka/cowboy-trails/pull/35) ([cabol](https://github.com/cabol))
- Added edoc to trails module. [\#34](https://github.com/inaka/cowboy-trails/pull/34) ([cabol](https://github.com/cabol))
- Cabol.add readme [\#33](https://github.com/inaka/cowboy-trails/pull/33) ([cabol](https://github.com/cabol))
- Add sort by id implementation in trails.erl [\#32](https://github.com/inaka/cowboy-trails/pull/32) ([davecaos](https://github.com/davecaos))
-  store/1 can receive Cowboy's \[route\_path\(\)\]  [\#31](https://github.com/inaka/cowboy-trails/pull/31) ([davecaos](https://github.com/davecaos))
- Add rebar.config file [\#30](https://github.com/inaka/cowboy-trails/pull/30) ([davecaos](https://github.com/davecaos))
- Example of Cowboy Trails Application [\#25](https://github.com/inaka/cowboy-trails/pull/25) ([davecaos](https://github.com/davecaos))
- Cabol.9.persistence [\#23](https://github.com/inaka/cowboy-trails/pull/23) ([cabol](https://github.com/cabol))
- \[\#21\] Changed elvis.config to use https instead of  in Makefile deps [\#22](https://github.com/inaka/cowboy-trails/pull/22) ([davecaos](https://github.com/davecaos))
- Add a method field to trails [\#20](https://github.com/inaka/cowboy-trails/pull/20) ([davecaos](https://github.com/davecaos))
- \[\#8\] Add metadata parameter to trails [\#18](https://github.com/inaka/cowboy-trails/pull/18) ([davecaos](https://github.com/davecaos))
- Cabol.7.implement function trails [\#17](https://github.com/inaka/cowboy-trails/pull/17) ([cabol](https://github.com/cabol))
- \[\#6\] trails:trail/2,3,4 implementation with tests [\#16](https://github.com/inaka/cowboy-trails/pull/16) ([davecaos](https://github.com/davecaos))
- \[\#5\] Add trails:single\_host\_compile\(\) and theirs tests [\#15](https://github.com/inaka/cowboy-trails/pull/15) ([davecaos](https://github.com/davecaos))
- Basic trails router implementation [\#14](https://github.com/inaka/cowboy-trails/pull/14) ([davecaos](https://github.com/davecaos))
- Test fixes [\#13](https://github.com/inaka/cowboy-trails/pull/13) ([elbrujohalcon](https://github.com/elbrujohalcon))
- Base trails app structure [\#12](https://github.com/inaka/cowboy-trails/pull/12) ([davecaos](https://github.com/davecaos))
- waffle.io Badge [\#2](https://github.com/inaka/cowboy-trails/pull/2) ([waffle-iron](https://github.com/waffle-iron))
- Update LICENSE [\#1](https://github.com/inaka/cowboy-trails/pull/1) ([elbrujohalcon](https://github.com/elbrujohalcon))

\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*


text:
<?php

include_once dirname(dirname(dirname(__FILE__))).'/thirdparty/nusoap/lib/nusoap.php';

/**
 * A client of a sharepoint server
 *
 * Implements a subset of features as we're waiting for CMIS...
 *
 * @author Marcus Nyeholt <marcus@silverstripe.com.au>
 */
class SharePointClient
{
	const LIST_WSDL = '/_vti_bin/Lists.asmx?wsdl';

	const ID_IDX = 'SS_SP_ID';

	const SEARCH_QUERY_OPTIONS = '<QueryOptions><ViewAttributes Scope="RecursiveAll" /></QueryOptions>';

	/**
	 * The URL being connected to
	 *
	 * @var String
	 */
	protected $url;

	/**
	 * The user connecting (needed for caching...)
	 * @var unknown_type
	 */
	protected $username;

	/**
	 * Need to store in case someone wants to download through this connection
	 * too.
	 *
	 * @var String
	 */
	protected $password;

	/**
	 * Connect the sharepoint client
	 *
	 * @param String $sharepointUrl
	 * @param String $username
	 * @param String $password
	 */
	public function connect($sharepointUrl, $username, $password)
	{
		$client = $this->getClient($sharepointUrl . self::LIST_WSDL);
		$auth = "$username:$password";

		$this->url = $sharepointUrl;
		$this->username = $username;
		$this->password = $password;

		$client->setCredentials("","","ntlm");
		$client->setCurlOption(CURLOPT_USERPWD, $auth);
	}

	public function isConnected()
	{
		return $this->soapClient != null;
	}

	public function disconnect()
	{

	}

	/**
	 * Gets all of the lists in this share point server
	 *
	 * @return unknown_type
	 */
	public function getLists()
	{
		$cacheKey = md5($this->url.'|getlists|'.$this->username);
		$data = CacheService::inst()->get($cacheKey);

		if (!$data) {

			$result = $this->getClient()->call('GetListCollection');

			$items = array();

			if (isset($result['GetListCollectionResult']['Lists']['List'])) {
		        $lists = $result['GetListCollectionResult']['Lists']['List'];
		        foreach ($lists as $list) {
	                /*$title = $list['!Title'];
	                $viewUrl = $list['!DefaultViewUrl'];
	                $webId = $list['!WebId'];*/
		        	$list = $this->sanitiseObject($list);
		        	// we want to store a special SS_ID here which is a joining
		        	// of the listID with the object id; obviously, lists
		        	// don't have the object id, but we'll do it to maintain
		        	// consistency
		        	$list[self::ID_IDX] = $list['ID'];
	                $items[$list['ID']] = $list;
		        }
			}

			CacheService::inst()->store($cacheKey, $items);
			return $items;
		}

		return $data;
	}

	/**
	 * Gets the children of a given object.
	 *
	 * The ObjectID in this case may be a list id, or a compound of
	 * the list and the item's ID in that list
	 *
	 * @param $objectId
	 * @return array
	 */
	public function getChildren($objectId, $folderPath = '')
	{
		$cacheKey = md5($this->url.'|getChildren|'.$objectId.'|'.$folderPath.'|'.$this->username);
		$data = CacheService::inst()->get($cacheKey);

		if (!is_array($data)) {
			$id = $this->getCompoundId($objectId);

			$childQueryArgs = array(
				'listName' => $id->listId
			);

			// if it's null ID, just list the top level of the
			// list
			if ($id->id) {
				$parentQueryOptions = '<QueryOptions><Folder>'.$folderPath.'</Folder></QueryOptions>';
				$childQueryArgs['queryOptions'] = array($parentQueryOptions);
			}

			$result = $this->getClient()->call('GetListItems', $childQueryArgs);

			$output = array();
			if (isset($result['GetListItemsResult']['listitems']['data']['row'])) {
				if ($result['GetListItemsResult']['listitems']['data']['!ItemCount'] == '1') {
					$output[] = $this->sanitiseObject($result['GetListItemsResult']['listitems']['data']['row'], $id->listId);
				} else {
					foreach ($result['GetListItemsResult']['listitems']['data']['row'] as $res) {
						$output[] = $this->sanitiseObject($res, $id->listId);
					}
				}
			}

			CacheService::inst()->store($cacheKey, $output);
			return $output;
		}

		return $data;
	}

	/**
	 * Gets an object based on its ID
	 *
	 * @param String $id
	 * @return array
	 */
	public function getObject($id)
	{
		$cacheKey = md5($this->url.'|getObject|'.$id.'|'.$this->username);
		$data = CacheService::inst()->get($cacheKey);

		if (!$data) {
			$id = $this->getCompoundId($id);

			if (!$id->id) {
				// just the list
				$lists = $this->getLists();
				return isset($lists[$id->listId]) ? $lists[$id->listId] : null;
			}

			$xml = <<<XML
			<Query>
			   <Where>
			      <Eq>
			         <FieldRef Name="ID" />
			         <Value Type="Counter">$id->id</Value>
			      </Eq>
			   </Where>
			</Query>
XML;
			$searchQueryArgs = array(
				'listName' => $id->listId,
				'queryOptions' => array(self::SEARCH_QUERY_OPTIONS),
				'query' => array($xml),
			);

			$result = $this->getClient()->call('GetListItems', $searchQueryArgs);

			// This result SHOULD be of the form
			/*Array
				(
				    [GetListItemsResult] => Array
				        (
				            [listitems] => Array
				                (
				                    [data] => Array
				                        (
				                            [row] => Array*/
			$obj = null;
			if (isset($result['GetListItemsResult']['listitems']['data']['row'])) {
				$obj = $this->sanitiseObject($result['GetListItemsResult']['listitems']['data']['row'], $id->listId);
				// set the compound ID

			}
			CacheService::inst()->store($cacheKey, $obj);
			return $obj;
		}

		return $data;
	}

	/**
	 * Get a compound ID from the passed in object ID
	 *
	 * A compound ID has the form
	 *
	 * {list-id-guid}:ID
	 *
	 * where the ID bit is optional
	 *
	 * @param String $objectId
	 * @return StdClass
	 */
	protected function getCompoundId($objectId)
	{
		$bits = explode(':', $objectId);
		$id = new StdClass;

		if (count($bits) == 2) {
			// compound
			list($id->listId, $id->id) = $bits;
		} else {
			$id->listId = $bits[0];
			$id->id = null;
		}

		if (!(strpos($id->listId, '{') === 0)) {
			throw new Exception("Passed in ID $objectId is invalid");
		}

		return $id;
	}

	/**
	 * Make the object a little more sane
	 */
	protected function sanitiseObject($in, $listId = null)
	{
		$new = array();

		foreach ($in as $key => $value) {
			$key = str_replace('!', '', $key);
			$key = preg_replace('/^ows_/', '', $key);

			// for some reason, some of the metadata properties have
			// a prefix of ID;#. Not sure why...
			// @TODO Fix this??
			$value = preg_replace('/^(\d+)\;\#/', '', $value);

			if ($key == 'MetaInfo') {
				$rows = explode("\n", $value);
				foreach ($rows as $row) {
					$fname = substr($row, 0, strpos($row, ':'));
					$value = substr($row, strpos($row, ':') + 1);
					if ($value{2} == '|') {
						$value = substr($value, 3);
					}
					$new[$fname] = $value;
				}
			}

			$new[$key] = $value;
		}

		if ($listId) {
			if (!isset($new['ID'])) {
				throw new Exception("Object ".var_export($in, true). ' has an invalid ID');
			}
			$new[self::ID_IDX] = $listId.':'.$new['ID'];
		}

		if (!isset($new['Title']) && isset($new['vti_title'])) {
			$new['Title'] = $new['vti_title'];
		}

		if (!isset($new['Title']) && isset($new['LinkFilename'])) {
			$new['Title'] = $new['LinkFilename'];
		}

		return $new;
	}

	/**
	 *
	 * @param String $fileRef
	 *			The "FileRef" property of an object to stream the content of
	 */
	public function streamObject(SharePointContentItem $object, $toFile='', $contentType = '')
	{
		$contentUrl = $this->url . '/' . str_replace('%2F', '/', rawurlencode($object->FileRef));

		$contentType = HTTP::getMimeType($object->FileRef);

		if (!$contentType) {
			$contentType = 'application/octet-stream';
		}

		$session = curl_init($contentUrl);
		curl_setopt($session, CURLOPT_USERPWD, $this->username.':'.$this->password);
		curl_setopt($session, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);

		if (!strlen($toFile)) {
			$filename = rawurlencode($object->LinkFilename);
			header("Content-Disposition: atachment; filename=$filename");
			header("Content-Type: $contentType");
			// header("Content-Length: ".filesize("$path/$filename"));
			header("Pragma: no-cache");
			header("Expires: 0");
			curl_exec($session);
		} else {
			// get the file and store it into a local item
			curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
			$response = curl_exec($session);
			$fp = fopen($toFile, 'w');
			if (!$fp) {
				throw new Exception("Could not write file to $toFile");
			}
			fwrite($fp, $response);
			fclose($fp);
		}

		curl_close($session);
	}

	/**
	 * The soap client we're using.
	 * @var unknown_type
	 */
	protected $soapClient;

	/**
	 * Get a soap client for the given wsdl
	 *
	 * @param String $url
	 * @return nusoap_client
	 */
	protected function getClient($url = '')
	{
		if (!$this->soapClient) {
			$this->soapClient = new nusoap_client($url, true);
		}

		return $this->soapClient;
	}
}

/* SAMPLE CODE ONLY
$searchQueryOptions = <<<XML
<QueryOptions>
	<ViewAttributes Scope="RecursiveAll" />
</QueryOptions>
XML;

$parentQueryOptions = <<<XML
<QueryOptions>
	<Folder>Shared Documents</Folder>
</QueryOptions>
XML;

$query = <<<XML
<Query>
   <Where>
      <Eq>
         <FieldRef Name="ID" />
         <Value Type="Counter">3</Value>
      </Eq>
   </Where>
</Query>
XML;

$childQueryArgs = array(
	'listName' => '1A545C57-1EEB-4B56-9B2D-0425296D6D74',
	'queryOptions' => array($parentQueryOptions),
);

$searchQueryArgs = array(
	'listName' => '1A545C57-1EEB-4B56-9B2D-0425296D6D74',
	'queryOptions' => array($searchQueryOptions),
	'query' => array($query),
);

$result = $client->call('GetListItems', $searchQueryArgs);*/
?>


text:
package sttp.client3.okhttp

import sttp.capabilities.WebSockets
import sttp.client3._
import sttp.client3.testing.ConvertToFuture
import sttp.client3.testing.websocket.{WebSocketBufferOverflowTest, WebSocketConcurrentTest, WebSocketTest}
import sttp.monad.{FutureMonad, MonadError}

import scala.concurrent.duration._
import scala.concurrent.{Future, blocking}

class OkHttpFutureWebsocketTest
    extends WebSocketTest[Future]
    with WebSocketBufferOverflowTest[Future]
    with WebSocketConcurrentTest[Future] {
  override val backend: SttpBackend[Future, WebSockets] = OkHttpFutureBackend()
  override implicit val convertToFuture: ConvertToFuture[Future] = ConvertToFuture.future
  override implicit val monad: MonadError[Future] = new FutureMonad()

  override def throwsWhenNotAWebSocket: Boolean = true
  override def bufferCapacity: Int = OkHttpBackend.DefaultWebSocketBufferCapacity.get

  override def eventually[T](interval: FiniteDuration, attempts: Int)(f: => Future[T]): Future[T] = {
    Future(blocking(Thread.sleep(interval.toMillis))).flatMap(_ => f).recoverWith {
      case _ if attempts > 0 => eventually(interval, attempts - 1)(f)
    }
  }

  override def concurrently[T](fs: List[() => Future[T]]): Future[List[T]] = Future.sequence(fs.map(_()))
}


text:
package com.lonepulse.icklebot.injector.implicit;

import java.lang.reflect.Field;
import java.util.Set;

import android.content.Context;
import android.util.Log;

import com.lonepulse.icklebot.injector.Injector;
import com.lonepulse.icklebot.injector.resolver.InjectionCategory;
import com.lonepulse.icklebot.util.ContextUtils;

/**
 *
An implementation of {@link Injector} which is responsible
 * for injecting System Services.

 *
 * @version 1.0.0
 *

 * @author Lahiru Sahan Jayasinghe
 */
class ImplicitSystemServiceInjector implements Injector {

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void inject(Configuration config) {

		Context context = ContextUtils.discover(config.getContext());

		Set<Field> fields = config.getInjectionTargets(InjectionCategory.SYSTEM_SERVICE);
		Field[] contextFields = Context.class.getDeclaredFields();

		for (Field field : fields) {

			try {

				for (Field contextField : contextFields) {

					if(contextField.getName().equalsIgnoreCase(field.getName())) {

						String identifier = (String) contextField.get(null);

						if(!field.isAccessible()) field.setAccessible(true);

						field.set(config.getContext(), context.getSystemService(identifier));
					}
				}
			}
			catch (Exception e) {

				Log.e(getClass().getName(), "Injection Failed!", e);
			}
		}
	}
}


text:
<?php

namespace Doctrine\Tests\Models\ValueConversionType;

use Doctrine\Common\Collections\ArrayCollection;

/**
 * @Entity
 * @Table(name="vct_inversed_onetomany_compositeid")
 */
class InversedOneToManyCompositeIdEntity
{
    /**
     * @Column(type="rot13")
     * @Id
     */
    public $id1;

    /**
     * @Column(type="rot13")
     * @Id
     */
    public $id2;

    /**
     * @Column(type="string", name="some_property")
     */
    public $someProperty;

    /**
     * @OneToMany(targetEntity="OwningManyToOneCompositeIdEntity", mappedBy="associatedEntity")
     */
    public $associatedEntities;

    public function __construct()
    {
        $this->associatedEntities = new ArrayCollection();
    }
}


text:
using System.Data;
using System.IO;
using Excel;

namespace SmartScheduler.Core
{
    public interface IExcelFileReader
    {
        DataSet Read(string filePath);
    }

    public class ExcelFileReader : IExcelFileReader
    {
        public DataSet Read(string filePath)
        {
            var stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
            var excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
            excelReader.IsFirstRowAsColumnNames = true;
            var result = excelReader.AsDataSet();
            excelReader.Close();
            return result;
        }
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SyncMeasureProject
{
    static class SyncMeasure
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new SyncMeasureForm());
        }
    }
}


text:
/*
 * decaffeinate suggestions:
 * DS102: Remove unnecessary code created because of implicit returns
 * DS207: Consider shorter variations of null checks
 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
 */

const _ = require("lodash");

import { MigrationMixin } from "./migration-mixin";

const migration = {
  version: "1.10.0",
  description: "Adds simulation engine settings",
  date: "2016-01-16",

  doUpdate(data) {
    if (data.settings == null) { data.settings = {}; }
    if (data.settings.simulation == null) { data.settings.simulation = {}; }

    return data.settings.simulation.newIntegration != null ? data.settings.simulation.newIntegration : (data.settings.simulation.newIntegration = false);
  }
};

export const migration_11 = _.mixin(migration, MigrationMixin);


text:
package com.jiffey.slick.additions

import com.jiffey.slick.additions.session._

import java.sql.SQLException

import scala.concurrent.{Future, future}
import scala.language.implicitConversions
import scala.slick.session.Session
import scala.slick.util.Logging

import scaldi.{Injectable, Injector}

class Database(implicit inj: Injector) extends Logging with Injectable {

  val db = inject [DatabaseComponent]
  val sessionProvider = inject [SlickSessionProvider]

  val dialect: DatabaseDialect[_] = db.dialect

  implicit def roToSession(roSession: ReadOnlySession): Session = roSession.session
  implicit def rwToSession(rwSession: ReadWriteSession): Session = rwSession.session

  def readOnlyAsync[T](f: ReadOnlySession => T): Future[T] =
    future(readOnly(f))(sessionProvider.executionContext)

  def readWriteAsync[T](f: ReadWriteSession => T): Future[T] =
    future(readWrite(f))(sessionProvider.executionContext)

  def readWriteAsync[T](attempts: Int)(f: ReadWriteSession => T): Future[T] =
    future(readWrite(attempts)(f))(sessionProvider.executionContext)

  def readOnly[T](f: ReadOnlySession => T): T = {
    var s: Option[Session] = None
    val ro = new ReadOnlySession({
      s = Some(sessionProvider.createReadOnlySession(db.handle))
      s.get
    })
    try f(ro) finally s.foreach(_.close())
  }

  def readWrite[T](f: ReadWriteSession => T): T = {
    val s = sessionProvider.createReadWriteSession(db.handle)
    try {
      s.withTransaction {
        f(new ReadWriteSession(s))
      }
    } finally s.close()
  }

  def readWrite[T](attempts: Int)(f: ReadWriteSession => T): T = {
    1 to attempts - 1 foreach { attempt =>
      try {
        return readWrite(f)
      } catch {
        case t: SQLException =>
          val throwableName = t.getClass.getSimpleName
          logger.warn(s"Failed ($throwableName) readWrite transaction attempt $attempt of $attempts")
      }
    }
    readWrite(f)
  }

}


text:
package com.pushtechnology.diffusion.examples.runnable;

import static com.pushtechnology.diffusion.client.topics.details.TopicType.BINARY;
import static com.pushtechnology.diffusion.transform.transformer.Transformers.byteArrayToBinary;
import static com.pushtechnology.diffusion.transform.updater.UpdaterBuilders.updaterBuilder;
import static java.util.concurrent.TimeUnit.SECONDS;

import java.nio.ByteBuffer;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Function;

import com.pushtechnology.diffusion.client.callbacks.ErrorReason;
import com.pushtechnology.diffusion.client.features.control.topics.TopicControl;
import com.pushtechnology.diffusion.client.features.control.topics.TopicUpdateControl;
import com.pushtechnology.diffusion.client.session.Session;
import com.pushtechnology.diffusion.datatype.binary.Binary;
import com.pushtechnology.diffusion.transform.updater.SafeTransformedUpdater;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A client that creates and updates Binary topics.
 *
 * @author Push Technology Limited
 */
public final class ProducingBinary extends AbstractClient {
    private static final Logger LOG = LoggerFactory.getLogger(ProducingBinary.class);
    private static final Function<RandomData, Binary> SERIALISER = new Function<RandomData, ByteBuffer>() {
        @Override
        public ByteBuffer apply(RandomData value) {
            final ByteBuffer buffer = ByteBuffer.allocate(16);
            buffer.putInt(value.getId());
            buffer.putLong(value.getTimestamp());
            buffer.putInt(value.getRandomInt());
            return buffer;
        }
    }
        .andThen(ByteBuffer::array)
        .andThen(byteArrayToBinary());
    private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();

    private volatile Future<?> updateTask;

    /**
     * Constructor.
     * @param url The URL to connect to
     * @param principal The principal to connect as
     */
    public ProducingBinary(String url, String principal) {
        super(url, principal);
    }

    @Override
    public void onConnected(Session session) {
        final TopicControl topicControl = session.feature(TopicControl.class);
        topicControl
            .addTopic("binary/random", BINARY)
            .thenAccept(result -> beginUpdating(session))
            .exceptionally(ex -> {
                LOG.error("Failed to add topic binary/random", ex);
                return null;
            });
    }

    private void beginUpdating(Session session) {
        LOG.debug("Begin updating topic");

        final TopicUpdateControl.Updater updater = session
            .feature(TopicUpdateControl.class)
            .updater();

        // Create a one-way transforming value updater that cannot be used to lookup cached values
        final SafeTransformedUpdater<Binary, RandomData> valueUpdater = updaterBuilder(Binary.class)
            .transform(SERIALISER)
            .create(updater);

        updateTask = EXECUTOR.scheduleAtFixedRate(
            () -> {
                valueUpdater.update(
                    "binary/random",
                    RandomData.next(),
                    new TopicUpdateControl.Updater.UpdateCallback.Default());
            },
            0L,
            1L,
            SECONDS);
    }

    @Override
    public void onDisconnected() {
        updateTask.cancel(false);
    }

    @Override
    public void onError(ErrorReason errorReason) {
        LOG.error("Failed to start client: {}", errorReason);
    }

    /**
     * Entry point for the example.
     * @param args The command line arguments
     * @throws InterruptedException If the main thread was interrupted
     */
    // CHECKSTYLE.OFF: UncommentedMain
    public static void main(String[] args) throws InterruptedException {
        final ProducingBinary client =
            new ProducingBinary("ws://diffusion.example.com:80", "auth");
        client.start("auth_secret");
        client.waitForStopped();
    }
    // CHECKSTYLE.ON: UncommentedMain
}