#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll ls(int x){return x<<1;}
ll rs(int x){return x<<1|1;}
const int N=100005;
ll n,m,t;
ll a[N];
struct node{
ll to,nxt;
}e[N<<1];
ll head[N<<1];
ll cnt;
void add(ll u,ll v){
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
ll deep[N],fa[N],son[N],siz[N];
void dfs1(ll x,ll father){
deep[x]=deep[father]+1;
fa[x]=father;
siz[x]=1;
for(int i=head[x];~i;i=e[i].nxt){
ll y=e[i].to;
if(y!=father){
dfs1(y,x);
siz[x]+=siz[y];
if(!son[x]||siz[y]>siz[son[x]]){
son[x]=y;
}
}
}
}
ll top[N],id[N],ans,w[N],z;
void dfs2(ll x,ll topx){
top[x]=topx;
id[x]=++ans;
if(!son[x])return;
dfs2(son[x],topx);
for(int i=head[x];~i;i=e[i].nxt){
ll y=e[i].to;
if(y!=fa[x]&&y!=son[x]){
dfs2(y,y);
}
}
}
ll tree[N<<2],tag[N<<2],L[N<<2],R[N<<2];
void push_up(ll p){
tree[p]=tree[ls(p)]+tree[rs(p)]+(L[rs(p)]==R[ls(p)]);
L[p]=L[ls(p)],R[p]=R[rs(p)];
}
void addtag(ll p,ll pl,ll pr,ll d){
tree[p]=pr-pl;
tag[p]=d;
L[p]=R[p]=d;
}
void push_down(ll p,ll pl,ll pr){
if(tag[p]){
ll mid=(pl+pr)>>1;
addtag(ls(p),pl,mid,tag[p]);
addtag(rs(p),mid+1,pr,tag[p]);
tag[p]=0;
}
}
void update(ll p,ll L,ll R,ll pl,ll pr,ll d){
if(L<=pl&&R>=pr){
addtag(p,pl,pr,d);
return;
}
push_down(p,pl,pr);
ll mid=(pl+pr)>>1;
if(L<=mid)update(ls(p),L,R,pl,mid,d);
if(R>mid)update(rs(p),L,R,mid+1,pr,d);
push_up(p);
}
void updatel(ll x,ll y,ll z){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
update(1,id[top[x]],id[x],1,n,z);
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
update(1,id[x],id[y],1,n,z);
}
ll query(ll p,ll LL,ll RR,ll pl,ll pr){
ll res=0;
if(LL<=pl&&RR>=pr){
return tree[p];
}
push_down(p,pl,pr);
ll mid=(pl+pr)>>1;
if(LL<=mid)res+=query(ls(p),LL,RR,pl,mid);
if(RR>mid)res+=query(rs(p),LL,RR,mid+1,pr);
if(LL<=mid&&RR>mid&&R[ls(p)]==L[rs(p)])res++;
return res;
}
int op(int p,int LL,int pl,int pr){
if(pl==pr)return L[p];
push_down(p,pl,pr);
int mid=(pl+pr)>>1;
if(LL<=mid)return op(ls(p),LL,pl,mid);
else return op(rs(p),LL,mid+1,pr);
}
ll queryl(ll x,ll y){
ll an=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
an+=query(1,id[top[x]],id[x],1,n);
if(op(1,id[fa[top[x]]],1,n)==op(1,id[top[x]],1,n))an++;
x=fa[top[x]];
}
if(deep[x]>deep[y])swap(x,y);
an+=query(1,id[x],id[y],1,n);
return an;
}
void build(int p,int pl,int pr){
tag[p]=0;
if(pl==pr){
tree[p]=0;
L[p]=R[p]=++z;
return;
}
int mid=(pl+pr)>>1;
build(ls(p),pl,mid);
build(rs(p),mid+1,pr);
push_up(p);
}
int main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--){
cnt=z=0;
for(int i=0;i<N*2;i++){
e[i].nxt=-1;
head[i]=-1;
tree[i]=tag[i]=L[i]=R[i]=0;
siz[i]=id[i]=fa[i]=top[i]=son[i]=w[i]=0;
}
cin>>n>>m;
for(int i=1;i<n;i++){
ll u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i=1;i<=m;i++){
ll o,x,y;
cin>>o;
if(o==1){
cin>>x>>y;
updatel(x,y,++z);
}else{
cin>>x>>y;
cout<<queryl(x,y)<<endl;
}
}
}
return 0;
}