code: def test_spmm(idtype, dtype, g, shp, msg, reducer):
      g = g.astype(idtype).to(F.ctx())
      print(g)
      print(g.idtype)
  
      hu = F.tensor(
          np.random.rand(*((g.number_of_src_nodes(),) + shp[0])).astype(
              dtype
          )
          + 1
      )
      he = F.tensor(
          np.random.rand(*((g.num_edges(),) + shp[1])).astype(dtype) + 1
      )
      print("u shape: {}, e shape: {}".format(F.shape(hu), F.shape(he)))
  
      g.srcdata["x"] = F.attach_grad(F.clone(hu))
      g.edata["w"] = F.attach_grad(F.clone(he))
      print(
          "SpMM(message func: {}, reduce func: {})".format(msg, reducer)
      )
  
      u = F.attach_grad(F.clone(hu))
      e = F.attach_grad(F.clone(he))
      with F.record_grad():
          v = gspmm(g, msg, reducer, u, e)
          if reducer in ["max", "min"]:
              v = F.replace_inf_with_zero(v)
          if g.num_edges() > 0:
              F.backward(F.reduce_sum(v))
              if msg != "copy_rhs":
                  grad_u = F.grad(u)
              if msg != "copy_lhs":
                  grad_e = F.grad(e)
  
      with F.record_grad():
          g.update_all(udf_msg[msg], udf_reduce[reducer])
          if g.num_edges() > 0:
              v1 = g.dstdata["v"]
              assert F.allclose(v, v1)
              print("forward passed")
  
              F.backward(F.reduce_sum(v1))
              if msg != "copy_rhs":
                  if reducer in [
                      "min",
                      "max",
                  ]:  # there might be some numerical errors
                      rate = F.reduce_sum(
                          F.abs(F.grad(g.srcdata["x"]) - grad_u)
                      ) / F.reduce_sum(F.abs(grad_u))
                      assert F.as_scalar(rate) < 1e-2, rate
                  else:
                      assert F.allclose(F.grad(g.srcdata["x"]), grad_u)
              if msg != "copy_lhs":
                  if reducer in ["min", "max"]:
                      rate = F.reduce_sum(
                          F.abs(F.grad(g.edata["w"]) - grad_e)
                      ) / F.reduce_sum(F.abs(grad_e))
                      assert F.as_scalar(rate) < 1e-2, rate
                  else:
                      assert F.allclose(F.grad(g.edata["w"]), grad_e)
              print("backward passed")
  
      g.srcdata.pop("x")
      g.edata.pop("w")
      if "v" in g.dstdata:
          g.dstdata.pop("v")
  
imports: import random
  import unittest
  import backend
  import dgl
  import numpy
  import pytest
  import torch
  from dgl.ops import gather_mm, gsddmm, gspmm, segment_reduce
  from utils import parametrize_idtype
  from utils.graph_cases import get_cases
label_desc: Use image node_id 4 for calling a global function with example usage: test_spmm(idtype, dtype, g, shp, msg, reducer) without return types