code: def test_grbcd_attack(model, budget, is_undirected):
      attack = GRBCDAttack(
          model(),
          block_size=10_000,
          epochs=4,
          log=False,
          is_undirected=is_undirected,
      )
      assert str(attack) == "GRBCDAttack()"
  
      x = torch.randn(8, 3)
      edge_index = torch.tensor(
          [[0, 1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7]]
      )
      if is_undirected:
          edge_index = to_undirected(edge_index)
  
      if model == GNN:
          y = torch.tensor([0])
          # All nodes belong to same graph:
          kwargs = dict(batch=edge_index.new_zeros(x.size(0)))
      else:
          y = torch.tensor([0, 1, 1, 0, 1, 0, 1, 0])
          kwargs = {}
  
      pert_edge_index, pert = attack.attack(
          x, edge_index, y, budget, **kwargs
      )
  
      m = edge_index.size(1)
      if budget == 1:
          assert pert.size() == (2, 1)
  
          if is_undirected:
              possible_m = [m - 2, m + 2]
          else:
              possible_m = [m - 1, m + 1]
          assert pert_edge_index.size(1) in possible_m
  
file_path: pytorch_geometric/test/contrib/nn/models/test_rbcd_attack.py
imports: import pytest
  import torch
  from torch.nn import Linear
  from torch_geometric.contrib.nn import GRBCDAttack, PRBCDAttack
  from torch_geometric.nn import GCNConv, global_add_pool
  from torch_geometric.utils import to_undirected
label_desc: Use image node_id 2 for calling a global function with example usage: test_grbcd_attack(model, budget, is_undirected) without return types