#include<bits/stdc++.h>
#include<cmath>
#define ll long long
#define For(i,a,b) for(ll i=a;i<=b;i++)
#define Rof(i,a,b) for(ll i=a;i>=b;i--)
#define N 100010
#define ls x<<1
#define rs x<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pb push_back
using namespace std;
vector<int >e[N];
int dfn[N],cnt=0,top[N],f[N],son[N],dep[N],sz[N];
int n,m;
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void dfs1(int u,int fa){
f[u]=fa;
dep[u]=dep[fa]+1;
sz[u]=1;
for(int v:e[u]){
if(v==fa) continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
void dfs2(int u,int fa,int tp){
top[u]=tp;
dfn[u]=++cnt;
if(!son[u]) return;
dfs2(son[u],u,tp);
for(int v:e[u]){
if(v==fa || v==son[u]) continue;
dfs2(v,u,v);
}
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=f[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
return u;
}
struct node{
int l,r,len,ans,tag;
}T[N<<2];
node merge(node x,node y){
node p;
p.len=x.len+y.len;
p.ans=x.ans+y.ans;
if(x.r==y.l) p.ans++;
p.l=x.l;
p.r=y.r;
return p;
}
void pushdown(int x){
if(T[x].tag){
T[ls].ans=T[ls].len-1;
T[rs].ans=T[rs].len-1;
T[ls].l=T[rs].l=T[ls].r=T[rs].r=T[ls].tag=T[rs].tag=T[x].tag;
T[x].tag=0;
}
return;
}
void build(int x,int l,int r){
T[x].len=r-l+1;
T[x].tag=T[x].ans=0;
if(l==r){
T[x].l=T[x].r=l;
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
T[x]=merge(T[ls],T[rs]);
}
void change(int x,int l,int r,int L,int R,int w){
if(L<=l && r<=R){
T[x].ans=T[x].len-1;
T[x].l=T[x].r=T[x].tag=w;
return;
}
pushdown(x);
int mid=(l+r)>>1;
if(L<=mid) change(lson,L,R,w);
if(R>mid) change(rson,L,R,w);
T[x]=merge(T[ls],T[rs]);
}
node qry(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return T[x];
pushdown(x);
int mid=(l+r)>>1;
if(R<=mid) return qry(lson,L,R);
if(L>mid) return qry(rson,L,R);
return merge(qry(lson,L,R),qry(rson,L,R));
}
void upd(int u,int v,int w){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
change(1,1,n,dfn[top[u]],dfn[u],w);
u=f[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
change(1,1,n,dfn[u],dfn[v],w);
}
int query(int u,int v){
int fu=lca(u,v);
node r1,r2;
r1.ans=r1.l=r1.len=r1.r=r1.tag=0;
r2.ans=r2.l=r2.len=r2.r=r2.tag=0;
while(top[u]!=top[fu]){
r1=merge(qry(1,1,n,dfn[top[u]],dfn[u]),r1);
u=f[top[u]];
}
r1=merge(qry(1,1,n,dfn[fu],dfn[u]),r1);
while(top[v]!=top[fu]){
r2=merge(qry(1,1,n,dfn[top[v]],dfn[v]),r2);
v=f[top[v]];
}
r2=merge(qry(1,1,n,dfn[fu],dfn[v]),r2);
return r1.ans+r2.ans;
}
void sol(){
n=read(),m=read();
For(i,1,n-1){
int u=read(),v=read();
e[u].pb(v);
e[v].pb(u);
}
dfs1(1,0);
dfs2(1,0,1);
build(1,1,n);
For(i,1,m){
int op=read(),u=read(),v=read();
if(op==1) upd(u,v,i+n);
else printf("%d\n",query(u,v));
}
For(i,1,n) e[i].clear(),dfn[i]=top[i]=son[i]=0;
cnt=0;
}
int main()
{
int T=read();
while(T--) sol();
return 0;
}