def test_weird_chars_in_lens_name(self, lens_name: str) -> None: """ Roundabout way to ensure some basic properties of filter generation. """ client = GraphClient() lens = LensView.get_or_create( gclient=client, lens_name=lens_name, lens_type="engagement", ) requery_lens = LensQuery().with_lens_name(lens_name).query_first( client) assert requery_lens.get_lens_name() == lens_name
def test_expected_data_in_dgraph(actix_session: str) -> None: # There is some unidentified, nondeterministic failure with e2e. # We fall into one of three buckets: # - No lens # - Lens with 3 scope # - Lens with 4 scope # - Lens with 5 scope (correct) query = LensQuery().with_lens_name(LENS_NAME) lens: LensView = wait_for_one(WaitForQuery(query), timeout_secs=TIMEOUT_SECS) assert lens.get_lens_name() == LENS_NAME # lens scope is not atomic def scope_has_N_items() -> bool: length = len(lens.get_scope()) logging.info(f"Expected 3+ nodes in scope, currently is {length}") # This number can change and, rather than trying to hammer it down, we're going # with a lower bound return length >= 3 wait_for_one(WaitForCondition(scope_has_N_items), timeout_secs=TIMEOUT_SECS) # Now that we've confirmed that the expected data has shown up in dgraph, # let's see what the GraphQL endpoint says. # TODO: Consider using `pytest-order` to make this a separate test that # depends on the above test having been run. gql_client = GraphqlEndpointClient(actix_session=actix_session) wait_for_one( WaitForNoException(lambda: ensure_graphql_lens_scope_no_errors( gql_client, LENS_NAME)), timeout_secs=TIMEOUT_SECS, )
def lens_to_dict(dgraph_client: DgraphClient, lens_name: str) -> List[Dict[str, Any]]: current_graph = get_lens_scope(dgraph_client, lens_name) LOGGER.info(f"Getting lens as dict {current_graph}") if not current_graph or not current_graph.get("scope"): return [] nodes = [] for graph in current_graph["scope"]: try: nodes.append(BaseView.from_dict(dgraph_client, graph)) except Exception as e: LOGGER.error("Failed to get NodeView from dict", e) if current_graph.get("scope"): current_graph.pop("scope") for node in nodes: node.expand() node.get_neighbor( EntityQuery, "expand(_all_)", "", EntityQuery().with_lenses( LensQuery().with_lens_name(eq=lens_name)), ) results = [{"node": current_graph, "edges": []}] lens_risks = get_lens_risks(dgraph_client, lens_name) for node in lens_risks: edges = [] risks = node.get("risks", []) if not risks: LOGGER.warning( f"Node in engagement graph has no connected risks {node}") for risk in risks: try: risk["node_key"] = node["node_key"] + risk["analyzer_name"] edge = { "from": node["node_key"], "edge_name": "risks", "to": risk["node_key"], } edges.append(edge) except Exception as e: LOGGER.error(f"risk edge failed: {risk} {e}") results.append({ "node": node, "edges": edges, }) results.extend([n.to_dict() for n in concrete_nodes]) results.extend(expanded_dynamic_nodes) return results
def test_expected_data_in_dgraph(self) -> None: query = LensQuery().with_lens_name(LENS_NAME) lens: LensView = wait_for_one(WaitForQuery(query), timeout_secs=120) assert lens.get_lens_name() == LENS_NAME # lens scope is not atomic def condition() -> bool: length = len(lens.get_scope()) logging.info(f"Expected 4 nodes in scope, currently is {length}") return length == 4 wait_for_one(WaitForCondition(condition), timeout_secs=240)
def with_lenses(self, *lenses: "LensQuery"): lenses = lenses or [LensQuery()] self.set_neighbor_filters("in_scope", [lenses]) for lens in lenses: lens.set_neighbor_filters("scope", [self]) return self
def wait_for_lens(): local_client = MasterGraphClient() query = LensQuery().with_lens_name(LENS_NAME) return WaitForLens(local_client, query)