code: def test_function_changed():
      ch = []
  
      class C(object):
          def _dep_changed(self, dep, **kwargs):
              ch.append(dep)
  
      ch_obj = C()
  
      def assert_changed(*objs):
          assert set(ch) == set(objs)
          while ch:
              ch.pop()
  
      fun1 = Function("void main(){$var1; $var2;}")
      fun1._dependents[ch_obj] = None
      fun1["var1"] = "x"
      fun1["var2"] = "y"
      assert_changed(fun1)
  
      fun1["var1"] = "z"
      assert_changed(fun1)
  
      # same value; should result in no change events
      fun1["var1"] = "z"
      assert_changed()
  
      fun1["var1"] = 0.5
      var1 = fun1["var1"]
      var1._dependents[ch_obj] = None
      assert_changed(fun1)
  
      var1.name = "xxx"
      assert_changed(fun1, var1)
  
      # changing type requires code change
      var1.value = 7
      assert_changed(fun1, var1)
  
      # changing value (but not type) requires no code changes
      var1.value = 6
      assert_changed()
  
      # test variable disconnect
      fun1["var1"] = Variable("var1", 7)
      var2 = fun1["var1"]
      var2._dependents[ch_obj] = None
      # assert_changed(fun1)
      # var2 is now connected
      var2.value = (1, 2, 3, 4)
      assert_changed(fun1, var2)
      # ..but var1 no longer triggers fun1.changed
      assert_changed()
      var1.value = 0.5
      assert_changed(var1)
  
      # test expressions
      fun2 = Function("float fn(float x){return $var1 + x;}")
      fun3 = Function("float fn(float x){return $var1 + x;}")
      exp1 = fun2(fun3(0.5))
      fun1["var2"] = exp1
      assert_changed(fun1)
  
      fun2._dependents[ch_obj] = None
      fun3._dependents[ch_obj] = None
      exp1._dependents[ch_obj] = None
  
      fun2["var1"] = "x"
      assert_changed(fun1, fun2, exp1)
  
      fun3["var1"] = "x"
      assert_changed(fun1, fun3, exp1)
  
      # test disconnect
      fun1["var2"] = fun2
      assert_changed(fun1)
      # triggers change
      fun2["var1"] = 0.9
      assert_changed(fun1, fun2, exp1)
      # no longer triggers change
      fun3["var1"] = 0.9
      assert_changed(fun3, exp1)
  
file_path: vispy/vispy/visuals/shaders/tests/test_function.py
imports: from vispy.visuals.shaders import Function, MainFunction, Variable, Varying, FunctionChain, StatementList
  from vispy.visuals.shaders.expression import FunctionCall, TextExpression
  from vispy.testing import assert_in, assert_not_in, assert_is, run_tests_if_main, assert_raises, assert_equal
label_desc: Use image node_id 7 for calling a global function with example usage: test_function_changed() without return types