Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

192 lines
6.0 KiB
Go

package languages
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zzet/gortex/internal/graph"
)
func emitEdgeTo(edges []*graph.Edge, kind graph.EdgeKind, to string) *graph.Edge {
for _, e := range edges {
if e.Kind == kind && e.To == to {
return e
}
}
return nil
}
func TestObjCExtractor_RNNativeEmit(t *testing.T) {
const objc = `#import "RCTEventEmitter.h"
@implementation BatteryModule
- (void)notify {
[self sendEventWithName:@"battery" body:@{@"level": @100}];
}
@end
`
res, err := NewObjCExtractor().Extract("BatteryModule.m", []byte(objc))
require.NoError(t, err)
topicID := "event::pubsub::rn_native_event::battery"
var topic *graph.Node
for _, n := range res.Nodes {
if n.ID == topicID {
topic = n
}
}
require.NotNil(t, topic, "native emit should materialise the rn_native_event topic node")
assert.Equal(t, graph.KindEvent, topic.Kind)
assert.Equal(t, "rn_native_event", topic.Meta["transport"])
emit := emitEdgeTo(res.Edges, graph.EdgeEmits, topicID)
require.NotNil(t, emit, "sendEventWithName: should emit an EdgeEmits to the topic")
assert.Equal(t, "BatteryModule.m::notify", emit.From, "emit attributed to the enclosing method")
}
func TestSwiftExtractor_RNNativeEmit(t *testing.T) {
const swift = `class BatteryModule {
func notify() {
sendEvent(withName: "battery", body: ["level": 100])
}
}
`
res, err := NewSwiftExtractor().Extract("BatteryModule.swift", []byte(swift))
require.NoError(t, err)
topicID := "event::pubsub::rn_native_event::battery"
emit := emitEdgeTo(res.Edges, graph.EdgeEmits, topicID)
require.NotNil(t, emit, "sendEvent(withName:) should emit an EdgeEmits to the topic")
assert.Equal(t, "BatteryModule.swift::BatteryModule.notify", emit.From, "emit attributed to the enclosing method")
}
func TestRNNativeEventEmitterListener(t *testing.T) {
// A JS NativeEventEmitter addListener re-homes onto the rn_native_event
// bridge (via the react-native import) so it shares the topic node with
// the native sendEventWithName: emitter.
src := `import { NativeEventEmitter, NativeModules } from 'react-native';
function subscribe() {
const emitter = new NativeEventEmitter(NativeModules.BatteryModule);
emitter.addListener('battery', onBattery);
}
`
fix := runTSExtractFixture(t, "app.ts", src)
events := fix.nodesByKind[graph.KindEvent]
require.Len(t, events, 1)
assert.Equal(t, "event::pubsub::rn_native_event::battery", events[0].ID)
assert.Equal(t, "rn_native_event", events[0].Meta["transport"])
assert.Len(t, fix.edgesByKind[graph.EdgeListensOn], 1)
}
func TestSwiftExtractor_RNCustomSendEventWrapper(t *testing.T) {
const swift = `class Notifier {
func emit() {
sendEvent(reactContext, "MyEvent", body)
}
}
`
res, err := NewSwiftExtractor().Extract("Notifier.swift", []byte(swift))
require.NoError(t, err)
topicID := "event::pubsub::rn_native_event::MyEvent"
emit := emitEdgeTo(res.Edges, graph.EdgeEmits, topicID)
require.NotNil(t, emit, "custom sendEvent(...) wrapper should emit an EdgeEmits to the topic")
assert.Equal(t, "Notifier.swift::Notifier.emit", emit.From, "emit attributed to the enclosing method")
count := 0
for _, e := range res.Edges {
if e.Kind == graph.EdgeEmits && e.To == topicID {
count++
}
}
assert.Equal(t, 1, count, "wrapper form must not double-count the emit edge")
}
func TestObjCExtractor_RNCustomSendEventWrapper(t *testing.T) {
const objc = `@implementation Notifier
- (void)emit {
sendEvent(self, @"MyEvent", @{});
}
@end
`
res, err := NewObjCExtractor().Extract("Notifier.m", []byte(objc))
require.NoError(t, err)
topicID := "event::pubsub::rn_native_event::MyEvent"
emit := emitEdgeTo(res.Edges, graph.EdgeEmits, topicID)
require.NotNil(t, emit, "ObjC paren-form sendEvent(...) wrapper should emit an EdgeEmits to the topic")
count := 0
for _, e := range res.Edges {
if e.Kind == graph.EdgeEmits && e.To == topicID {
count++
}
}
assert.Equal(t, 1, count, "wrapper form must not double-count the emit edge")
}
func TestKotlinExtractor_RNJVMEmit(t *testing.T) {
const kt = `package com.example
class ScoreModule(reactContext: ReactApplicationContext) {
fun broadcast() {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java).emit("Score", params)
}
}
`
res, err := NewKotlinExtractor().Extract("ScoreModule.kt", []byte(kt))
require.NoError(t, err)
topicID := "event::pubsub::rn_native_event::Score"
emit := emitEdgeTo(res.Edges, graph.EdgeEmits, topicID)
require.NotNil(t, emit, "getJSModule(...).emit(\"Score\") should emit an EdgeEmits to the topic")
assert.NotEmpty(t, emit.From, "emit attributed to the enclosing method")
}
func TestJavaExtractor_RNJVMEmit(t *testing.T) {
const j = `package com.example;
public class ScoreModule {
void broadcast() {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("Score", params);
}
}
`
res, err := NewJavaExtractor().Extract("ScoreModule.java", []byte(j))
require.NoError(t, err)
topicID := "event::pubsub::rn_native_event::Score"
emit := emitEdgeTo(res.Edges, graph.EdgeEmits, topicID)
require.NotNil(t, emit, "getJSModule(...).emit(\"Score\") should emit an EdgeEmits to the topic")
assert.NotEmpty(t, emit.From, "emit attributed to the enclosing method")
}
func TestKotlinExtractor_RNSendEventWrapper(t *testing.T) {
const kt = `package com.example
class ScoreModule {
fun broadcast() {
sendEvent(reactContext, "Score", params)
}
}
`
res, err := NewKotlinExtractor().Extract("ScoreModule.kt", []byte(kt))
require.NoError(t, err)
topicID := "event::pubsub::rn_native_event::Score"
emit := emitEdgeTo(res.Edges, graph.EdgeEmits, topicID)
require.NotNil(t, emit, "sendEvent(reactContext, \"Score\", ...) should emit an EdgeEmits to the topic")
count := 0
for _, e := range res.Edges {
if e.Kind == graph.EdgeEmits && e.To == topicID {
count++
}
}
assert.Equal(t, 1, count, "wrapper form must not double-count the emit edge")
}